#include "GameLogic.h"


//////////////////////////////////////////////////////////////////////////
//扑克信息
void ZeroMemory(void *data, int size)
{
    memset(data, 0, size);
}

void CopyMemory( void * destination, const void * source, size_t num){
    memcpy(destination, source, num);
}


const BYTE	DDZCGameLogicSingle::m_cbCardData[FULL_COUNT]=
{
	0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,	 
	0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,	 
	0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,	 
	0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,	 
	0x4E,0x4F,
};

//////////////////////////////////////////////////////////////////////////

DDZCGameLogicSingle::DDZCGameLogicSingle()
{
    srand(time(0));
}
 
DDZCGameLogicSingle::~DDZCGameLogicSingle()
{
}




void DDZCGameLogicSingle::PrintCard(BYTE cbBackCardData[], BYTE cbCardCount)
{
 
	SortCardList(cbBackCardData, cbCardCount, ST_ORDER) ;
	for (int num=0;num<cbCardCount;num++)
	{
		printf("%d  ",GetCardValue(cbBackCardData[num]));
	}
	printf(
		   "\n");
}
int DDZCGameLogicSingle::CountArray(const BYTE Array[])
{
	return (sizeof(Array)/sizeof(BYTE));
    
	
}

BYTE DDZCGameLogicSingle::GetCardType(const BYTE cbCardData[], BYTE cbCardCount)
{ 
	switch (cbCardCount)
	{
        case 0:	 
		{
			return CT_ERROR;
		}
        case 1:  
		{
			return CT_SINGLE;
		}
        case 2:	 
		{ 
			if ((cbCardData[0]==0x4F)&&(cbCardData[1]==0x4E)) return CT_MISSILE_CARD;
			if (GetCardLogicValue(cbCardData[0])==GetCardLogicValue(cbCardData[1])) return CT_DOUBLE;
            
			return CT_ERROR;
		}
	}
     
	tagAnalyseResult AnalyseResult;
	AnalysebCardData(cbCardData,cbCardCount,AnalyseResult);
     
	if (AnalyseResult.cbBlockCount[3]>0)
	{ 
		if ((AnalyseResult.cbBlockCount[3]==1)&&(cbCardCount==4)) return CT_BOMB_CARD;
		if ((AnalyseResult.cbBlockCount[3]==1)&&(cbCardCount==6)) return CT_FOUR_LINE_TAKE_ONE;
		if (
			cbCardCount==8 && (AnalyseResult.cbBlockCount[3]*4 == 8 || AnalyseResult.cbBlockCount[3]==1 && AnalyseResult.cbBlockCount[1]==2) )
			return CT_FOUR_LINE_TAKE_TWO;
        
		return CT_ERROR;
	}
    
	if (AnalyseResult.cbBlockCount[2]>0)
	{
	 	if (AnalyseResult.cbBlockCount[2]>1)
		{
	 		BYTE cbCardData=AnalyseResult.cbCardData[2][0];
			BYTE cbFirstLogicValue=GetCardLogicValue(cbCardData);
            
	 		if (cbFirstLogicValue>=15) return CT_ERROR;
            
	 		for (BYTE i=1;i<AnalyseResult.cbBlockCount[2];i++)
			{
				BYTE cbCardData=AnalyseResult.cbCardData[2][i*3];
				if (cbFirstLogicValue!=(GetCardLogicValue(cbCardData)+i)) return CT_ERROR;
			}
		}
		else if( cbCardCount == 3 ) return CT_THREE;
         
		if (AnalyseResult.cbBlockCount[2]*3==cbCardCount) return CT_THREE_LINE;
		if (AnalyseResult.cbBlockCount[2]*4==cbCardCount) return CT_THREE_LINE_TAKE_ONE;
		if ((AnalyseResult.cbBlockCount[2]*5==cbCardCount)&&(AnalyseResult.cbBlockCount[1]==AnalyseResult.cbBlockCount[2])) return CT_THREE_LINE_TAKE_TWO;
        
		return CT_ERROR;
	}
     
	if (AnalyseResult.cbBlockCount[1]>=3)
	{ 
		BYTE cbCardData=AnalyseResult.cbCardData[1][0];
		BYTE cbFirstLogicValue=GetCardLogicValue(cbCardData);
         
		if (cbFirstLogicValue>=15) return CT_ERROR;
         
		for (BYTE i=1;i<AnalyseResult.cbBlockCount[1];i++)
		{
			BYTE cbCardData=AnalyseResult.cbCardData[1][i*2];
			if (cbFirstLogicValue!=(GetCardLogicValue(cbCardData)+i)) return CT_ERROR;
		}
         
		if ((AnalyseResult.cbBlockCount[1]*2)==cbCardCount) return CT_DOUBLE_LINE;
        
		return CT_ERROR;
	}
     
	if ((AnalyseResult.cbBlockCount[0]>=5)&&(AnalyseResult.cbBlockCount[0]==cbCardCount))
	{ 
		BYTE cbCardData=AnalyseResult.cbCardData[0][0];
		BYTE cbFirstLogicValue=GetCardLogicValue(cbCardData);
         
		if (cbFirstLogicValue>=15) return CT_ERROR;
         
		for (BYTE i=1;i<AnalyseResult.cbBlockCount[0];i++)
		{
			BYTE cbCardData=AnalyseResult.cbCardData[0][i];
			if (cbFirstLogicValue!=(GetCardLogicValue(cbCardData)+i)) return CT_ERROR;
		}
        
		return CT_SINGLE_LINE;
	}
    
	return CT_ERROR;
}
 
void DDZCGameLogicSingle::SortCardList(BYTE cbCardData[], BYTE cbCardCount, BYTE cbSortType)
{ 
	if (cbCardCount==0) return;
	if (cbSortType==ST_CUSTOM) return;
     
	BYTE cbSortValue[MAX_COUNT];
	for (BYTE i=0;i<cbCardCount;i++) cbSortValue[i]=GetCardLogicValue(cbCardData[i]);
     
	bool bSorted=true;
	BYTE cbSwitchData=0,cbLast=cbCardCount-1;
	do
	{
		bSorted=true;
		for (BYTE i=0;i<cbLast;i++)
		{
			if ((cbSortValue[i]<cbSortValue[i+1])||
				((cbSortValue[i]==cbSortValue[i+1])&&(cbCardData[i]<cbCardData[i+1])))
			{ 
				bSorted=false;
                 
				cbSwitchData=cbCardData[i];
				cbCardData[i]=cbCardData[i+1];
				cbCardData[i+1]=cbSwitchData;
                 
				cbSwitchData=cbSortValue[i];
				cbSortValue[i]=cbSortValue[i+1];
				cbSortValue[i+1]=cbSwitchData;
			}
		}
		cbLast--;
	} while(bSorted==false);
     
	if (cbSortType==ST_COUNT)
	{ 
		BYTE cbCardIndex=0;
        
		tagAnalyseResult AnalyseResult;
		AnalysebCardData(&cbCardData[cbCardIndex],cbCardCount-cbCardIndex,AnalyseResult);
        
		for (BYTE i=0;i<sizeof(AnalyseResult.cbBlockCount);i++)
		{
			BYTE cbIndex=sizeof(AnalyseResult.cbBlockCount)-i-1;
			CopyMemory(&cbCardData[cbCardIndex],AnalyseResult.cbCardData[cbIndex],AnalyseResult.cbBlockCount[cbIndex]*(cbIndex+1)*sizeof(BYTE));
            
			cbCardIndex+=AnalyseResult.cbBlockCount[cbIndex]*(cbIndex+1)*sizeof(BYTE);
		}
	}
    
	return;
}

void DDZCGameLogicSingle::RandCardList(BYTE cbCardBuffer[], BYTE cbBufferCount)
{ 
	BYTE cbCardData[54];
	CopyMemory(cbCardData,m_cbCardData,sizeof(m_cbCardData));
	BYTE cbRandCount=0,cbPosition=0;
	do
	{
        
		cbPosition=rand()%(cbBufferCount-cbRandCount);
		cbCardBuffer[cbRandCount++]=cbCardData[cbPosition];
		cbCardData[cbPosition]=cbCardData[cbBufferCount-cbRandCount];
	} while (cbRandCount<cbBufferCount);
    
	return;
}

 
bool DDZCGameLogicSingle::RemoveCard(const BYTE cbRemoveCard[], BYTE cbRemoveCount, BYTE cbCardData[], BYTE cbCardCount)
{
    
    BYTE cbDeleteCount=0,cbTempCardData[MAX_COUNT];
	if (cbCardCount>sizeof(cbTempCardData)) return false;
	CopyMemory(cbTempCardData,cbCardData,cbCardCount*sizeof(cbCardData[0]));
     
	for (BYTE i=0;i<cbRemoveCount;i++)
	{
		for (BYTE j=0;j<cbCardCount;j++)
		{
			if (cbRemoveCard[i]==cbTempCardData[j])
			{
				cbDeleteCount++;
				cbTempCardData[j]=0;
				break;
			}
		}
	}
	if (cbDeleteCount!=cbRemoveCount) return false;
    BYTE cbCardPos=0;
	for (BYTE i=0;i<cbCardCount;i++)
	{
		if (cbTempCardData[i]!=0) cbCardData[cbCardPos++]=cbTempCardData[i];
	}
    
	return true;
}
 
void DDZCGameLogicSingle::SortOutCardList(BYTE cbCardData[], BYTE cbCardCount)
{ 
	BYTE cbCardType = GetCardType(cbCardData,cbCardCount);
    
	if( cbCardType == CT_THREE_LINE_TAKE_ONE || cbCardType == CT_THREE_LINE_TAKE_TWO )
	{
		tagAnalyseResult AnalyseResult = {};
		AnalysebCardData( cbCardData,cbCardCount,AnalyseResult );
        
		cbCardCount = AnalyseResult.cbBlockCount[2]*3;
		CopyMemory( cbCardData,AnalyseResult.cbCardData[2],sizeof(BYTE)*cbCardCount );
		for( int i = sizeof(AnalyseResult.cbBlockCount)-1; i >= 0; i-- )
		{
			if( i == 2 ) continue;
            
			if( AnalyseResult.cbBlockCount[i] > 0 )
			{
				CopyMemory( &cbCardData[cbCardCount],AnalyseResult.cbCardData[i],
                           sizeof(BYTE)*(i+1)*AnalyseResult.cbBlockCount[i] );
				cbCardCount += (i+1)*AnalyseResult.cbBlockCount[i];
			}
		}
	}
	else if( cbCardType == CT_FOUR_LINE_TAKE_ONE || cbCardType == CT_FOUR_LINE_TAKE_TWO )
	{
		tagAnalyseResult AnalyseResult = {};
		AnalysebCardData( cbCardData,cbCardCount,AnalyseResult );
        
		cbCardCount = AnalyseResult.cbBlockCount[3]*4;
		CopyMemory( cbCardData,AnalyseResult.cbCardData[3],sizeof(BYTE)*cbCardCount );
		for( int i = sizeof(AnalyseResult.cbBlockCount)-1; i >= 0; i-- )
		{
			if( i == 3 ) continue;
            
			if( AnalyseResult.cbBlockCount[i] > 0 )
			{
				CopyMemory( &cbCardData[cbCardCount],AnalyseResult.cbCardData[i],
                           sizeof(BYTE)*(i+1)*AnalyseResult.cbBlockCount[i] );
				cbCardCount += (i+1)*AnalyseResult.cbBlockCount[i];
			}
		}
	}
    
	return;
}

bool DDZCGameLogicSingle::IsValidCard(BYTE cbCardData)
{ 
	BYTE cbCardColor=GetCardColor(cbCardData);
	BYTE cbCardValue=GetCardValue(cbCardData);
    
	if ((cbCardData==0x4E)||(cbCardData==0x4F)) return true;
	if ((cbCardColor<=0x30)&&(cbCardValue>=0x01)&&(cbCardValue<=0x0D)) return true;
    
	return false;
}

BYTE DDZCGameLogicSingle::GetCardLogicValue(BYTE cbCardData)
{
	BYTE cbCardColor=GetCardColor(cbCardData);
	BYTE cbCardValue=GetCardValue(cbCardData);
    
	if (cbCardColor==0x40) return cbCardValue+2;
	return (cbCardValue<=2)?(cbCardValue+13):cbCardValue;
}

bool DDZCGameLogicSingle::CompareCard(const BYTE cbFirstCard[], const BYTE cbNextCard[], BYTE cbFirstCount, BYTE cbNextCount)
{
	BYTE cbNextType=GetCardType(cbNextCard,cbNextCount);
	BYTE cbFirstType=GetCardType(cbFirstCard,cbFirstCount);
	if (cbNextType==CT_ERROR) return false;
	if (cbNextType==CT_MISSILE_CARD) return true;
	if ((cbFirstType!=CT_BOMB_CARD)&&(cbNextType==CT_BOMB_CARD)) return true;
	if ((cbFirstType==CT_BOMB_CARD)&&(cbNextType!=CT_BOMB_CARD)) return false;
    if ((cbFirstType!=cbNextType)||(cbFirstCount!=cbNextCount)) return false;
    
	switch (cbNextType)
	{
        case CT_SINGLE:
        case CT_DOUBLE:
        case CT_THREE:
        case CT_SINGLE_LINE:
        case CT_DOUBLE_LINE:
        case CT_THREE_LINE:
        case CT_BOMB_CARD:
		{
			BYTE cbNextLogicValue=GetCardLogicValue(cbNextCard[0]);
			BYTE cbFirstLogicValue=GetCardLogicValue(cbFirstCard[0]);
            
			return cbNextLogicValue>cbFirstLogicValue;
		}
        case CT_THREE_LINE_TAKE_ONE:
        case CT_THREE_LINE_TAKE_TWO:
		{
			tagAnalyseResult NextResult;
			tagAnalyseResult FirstResult;
			AnalysebCardData(cbNextCard,cbNextCount,NextResult);
			AnalysebCardData(cbFirstCard,cbFirstCount,FirstResult);
            
			BYTE cbNextLogicValue=GetCardLogicValue(NextResult.cbCardData[2][0]);
			BYTE cbFirstLogicValue=GetCardLogicValue(FirstResult.cbCardData[2][0]);
            
			return cbNextLogicValue>cbFirstLogicValue;
		}
        case CT_FOUR_LINE_TAKE_ONE:
        case CT_FOUR_LINE_TAKE_TWO:
		{
			tagAnalyseResult NextResult;
			tagAnalyseResult FirstResult;
			AnalysebCardData(cbNextCard,cbNextCount,NextResult);
			AnalysebCardData(cbFirstCard,cbFirstCount,FirstResult);
        
            
            BYTE cbNextLogicValue=GetCardLogicValue(NextResult.cbCardData[3][0]);
			BYTE cbFirstLogicValue=GetCardLogicValue(FirstResult.cbCardData[3][0]);
            
			return cbNextLogicValue>cbFirstLogicValue;
		}
	}
	
	return false;
}


BYTE DDZCGameLogicSingle::MakeCardData(BYTE cbValueIndex, BYTE cbColorIndex)
{
	return (cbColorIndex<<4)|(cbValueIndex+1);
}


bool DDZCGameLogicSingle::_TestOutAllCard(WORD wTestUser, BYTE cbWantOutCardData[], BYTE cbWantOutCardCount, BYTE	cbAllCardData[GAME_PLAYER][MAX_COUNT], BYTE cbUserCardCount[GAME_PLAYER], bool bFirstOutCard)
{
	WORD wFriendID = GAME_PLAYER ;
	if(wTestUser != m_wBankerUser) wFriendID = (wTestUser==((m_wBankerUser+1)%GAME_PLAYER)) ? (m_wBankerUser+2)%GAME_PLAYER : (m_wBankerUser+1)%GAME_PLAYER ;
    
    BYTE cbWantOutCardType = GetCardType(cbWantOutCardData, cbWantOutCardCount) ;
    
	if ( cbUserCardCount[wTestUser] == cbWantOutCardCount ) return true ;
    
	try
	{
		for(WORD wUser=0; wUser<GAME_PLAYER; ++wUser)
		{
			if(wUser!=wTestUser && wFriendID!=wUser)
			{
				tagOutCardTypeResult CardTypeResult[12+1] ;
				ZeroMemory(CardTypeResult, sizeof(CardTypeResult)) ;
              	try
				{
					AnalyseOutCardType(cbAllCardData[wUser], cbUserCardCount[wUser], cbWantOutCardData, cbWantOutCardCount, CardTypeResult) ;
				}
				catch(...)
				{
					return false ;
				}
				for(BYTE cbCardType=CT_SINGLE; cbCardType<=CT_MISSILE_CARD; ++cbCardType)
					if(CardTypeResult[cbCardType].cbCardTypeCount>0) return false ;
			}
		}
	}
	catch(...)
	{
		return false ;
	}
     
	BYTE cbAllBombCard[MAX_COUNT], cbAllBombCount=0 ;
	GetAllBomCard(cbAllCardData[wTestUser], cbUserCardCount[wTestUser], cbAllBombCard, cbAllBombCount) ;
	if (cbAllBombCount > 0)
	{ 
		BYTE cbRemainCard[MAX_COUNT], cbRemainCardCount ;
        
		CopyMemory(cbRemainCard, cbAllCardData[wTestUser], cbUserCardCount[wTestUser]) ;
		cbRemainCardCount = cbUserCardCount[wTestUser] ;
        
		RemoveCard(cbWantOutCardData, cbWantOutCardCount, cbRemainCard, cbRemainCardCount) ;
		cbRemainCardCount -= cbWantOutCardCount ;
        
		if (CT_FOUR_LINE_TAKE_ONE == cbWantOutCardType || CT_FOUR_LINE_TAKE_TWO==cbWantOutCardType) return false ;
        
		if (cbWantOutCardType >= CT_BOMB_CARD && cbWantOutCardCount == cbUserCardCount[wTestUser]) return true ;
        
		if (cbAllBombCount == cbUserCardCount[wTestUser] && cbWantOutCardType >= CT_BOMB_CARD) return true ;
        
        if ( cbWantOutCardType >= CT_BOMB_CARD && GetCardType(cbRemainCard, cbRemainCardCount) != CT_ERROR &&
			CT_FOUR_LINE_TAKE_TWO != GetCardType(cbRemainCard, cbRemainCardCount) && CT_FOUR_LINE_TAKE_ONE != GetCardType(cbRemainCard, cbRemainCardCount) )
			return true ;
        
		if (cbWantOutCardType >= CT_BOMB_CARD && bFirstOutCard)
		{
			if (wTestUser != m_wBankerUser && GetCardType(m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser]) == CT_ERROR)
				return false ;
            
			WORD wUndersideOfBanker = (m_wBankerUser+1)%GAME_PLAYER ;	
			WORD wUpsideOfBanker = (wUndersideOfBanker+1)%GAME_PLAYER ;
             
			if (wTestUser == m_wBankerUser && GetCardType(m_cbAllCardData[wUndersideOfBanker], m_cbUserCardCount[wUndersideOfBanker]) == CT_ERROR &&
				GetCardType(m_cbAllCardData[wUpsideOfBanker], m_cbUserCardCount[wUpsideOfBanker]) == CT_ERROR)
				return false ;
		}
         
		if (cbWantOutCardType < CT_FOUR_LINE_TAKE_ONE && cbWantOutCardType != CT_SINGLE_LINE)
		{
			for (BYTE i=0; i < cbWantOutCardCount; ++i)
				for (BYTE j=0; j < cbAllBombCount; ++j)
				{
					if (GetCardValue(cbAllBombCard[j]) == GetCardValue(cbWantOutCardData[i])) return false ;
				}
		}
	}
    
	if(cbUserCardCount[wTestUser]==0) return true ;
     
	try
	{
		if (cbUserCardCount[wTestUser] < cbWantOutCardCount ) return false ;
		RemoveCard(cbWantOutCardData, cbWantOutCardCount, cbAllCardData[wTestUser], cbUserCardCount[wTestUser]) ;
		cbUserCardCount[wTestUser] -= cbWantOutCardCount ;
         
		if (cbWantOutCardType >= CT_THREE_LINE_TAKE_ONE && cbWantOutCardType <= CT_FOUR_LINE_TAKE_TWO && !bFirstOutCard)
		{
			bool bHaveLargeCard = false ;
			for (BYTE i = 3; i < cbWantOutCardCount; ++i)
				if (GetCardLogicValue(cbWantOutCardData[i]) >= 15)
				{
					bHaveLargeCard = true ;
					break ;
				}
            if (bHaveLargeCard)
            {
                for (BYTE i = 0; i < cbUserCardCount[wTestUser]; ++i)
                    if (GetCardLogicValue(cbAllCardData[wTestUser][i]) < 15) return false ;
            }
		}
	}
	catch(...)
	{
		return false ;
	}
	if(cbUserCardCount[wTestUser]!=0)
	{
		tagOutCardTypeResult CardTypeResult[12+1] ;
		ZeroMemory(CardTypeResult, sizeof(CardTypeResult)) ;
         
		try
		{
			AnalyseOutCardType(cbAllCardData[wTestUser], cbUserCardCount[wTestUser], CardTypeResult) ;
		}
		catch(...)
		{
			return false ;
		}
		for(BYTE cbCardType=CT_SINGLE; cbCardType<=CT_MISSILE_CARD; ++cbCardType)
			if(CardTypeResult[cbCardType].cbCardTypeCount>0)
			{
				for(long lIndex=0; lIndex<CardTypeResult[cbCardType].cbCardTypeCount; ++lIndex)
				{ 
					BYTE cbTmpCardData[GAME_PLAYER][MAX_COUNT], cbTmpCardCount[GAME_PLAYER] ;
					CopyMemory(cbTmpCardData, cbAllCardData, sizeof(cbTmpCardData)) ;
					CopyMemory(cbTmpCardCount, cbUserCardCount, sizeof(cbTmpCardCount)) ;
                     
					try
					{
						if(_TestOutAllCard(wTestUser, CardTypeResult[cbCardType].cbCardData[lIndex], CardTypeResult[cbCardType].cbEachHandCardCount[lIndex], cbTmpCardData, cbTmpCardCount, bFirstOutCard))
							return true ;
					}
					catch(...)
					{
						return false ;
					}
				}
			}
	}
	else
		return true ;
    
	return false ;
}

bool DDZCGameLogicSingle::AnalyseFourCardType( BYTE const cbHandCardData[MAX_COUNT], BYTE cbHandCardCount, BYTE cbEnemyCardData[MAX_COUNT], BYTE cbEnemyCardCount, tagOutCardResult &CardResult )
{

	ZeroMemory(&CardResult, sizeof(CardResult)) ;
    if ( cbHandCardCount < 5 ) return false ;
    
	if ( GetCardType(cbEnemyCardData, cbEnemyCardCount) == CT_SINGLE )
	{
		if ( GetCardLogicValue(cbHandCardData[1] ) < 16 )
		{
			tagAnalyseResultA AnalyseResult ;
			AnalysebCardDataA(cbHandCardData, cbHandCardCount, AnalyseResult) ;
            
			if ( cbHandCardCount != ( AnalyseResult.bFourCount * 4 + AnalyseResult.bDoubleCount * 2 + AnalyseResult.bSignedCount ) ||
				AnalyseResult.bFourCount <= 0 ) return false ;
            
			if ( GetCardType(cbEnemyCardData, cbEnemyCardCount) == CT_SINGLE )
			{
				if ( AnalyseResult.bSignedCount < 2 ) return false ;
                
				if ( GetCardLogicValue(AnalyseResult.m_bSCardData[0]) >= GetCardLogicValue(cbEnemyCardData[0]) ) return false ;
                
				if ( AnalyseResult.bFourCount >= 1 && AnalyseResult.bSignedCount == 2 )
				{
					BYTE cbFourCardIndex = ( AnalyseResult.bFourCount - 1 ) * 4 ;
                    
					CardResult.cbCardCount = 4 + 2 ;
					CopyMemory(CardResult.cbResultCard, AnalyseResult.m_bFCardData + cbFourCardIndex, 4 ) ;
					CardResult.cbResultCard[4] = AnalyseResult.m_bSCardData[0] ;
					CardResult.cbResultCard[5] = AnalyseResult.m_bSCardData[1] ;
                    
					return true ;
				}
				else if ( AnalyseResult.bFourCount >= 1 && AnalyseResult.bSignedCount == 3 )
				{
					BYTE cbFourCardIndex = ( AnalyseResult.bFourCount - 1 ) * 4 ;
                    
					CardResult.cbCardCount = 4 + 2 ;
					CopyMemory(CardResult.cbResultCard, AnalyseResult.m_bFCardData + cbFourCardIndex, 4 ) ;
					CardResult.cbResultCard[4] = AnalyseResult.m_bSCardData[1] ;
					CardResult.cbResultCard[5] = AnalyseResult.m_bSCardData[2] ;
                    
					return true ;
				}
			}
			else if ( GetCardType(cbEnemyCardData, cbEnemyCardCount) == CT_DOUBLE )
			{
			}
            
		}
		else if ( GetCardLogicValue(cbHandCardData[1] ) == 16 )
		{
			tagAnalyseResultA AnalyseResult ;
			AnalysebCardDataA(cbHandCardData, cbHandCardCount, AnalyseResult) ;
            
			if ( cbHandCardCount != ( AnalyseResult.bFourCount * 4 + AnalyseResult.bDoubleCount * 2 + AnalyseResult.bSignedCount ) ||
				AnalyseResult.bFourCount <= 0 ) return false ;
            
			if ( GetCardType(cbEnemyCardData, cbEnemyCardCount) == CT_SINGLE )
			{
				if ( AnalyseResult.bSignedCount < 4 ) return false ;
                
				if ( GetCardLogicValue(AnalyseResult.m_bSCardData[2]) >= GetCardLogicValue(cbEnemyCardData[0]) ) return false ;
                
				if ( AnalyseResult.bFourCount >= 1 && AnalyseResult.bSignedCount == 4 )
				{
					BYTE cbFourCardIndex = ( AnalyseResult.bFourCount - 1 ) * 4 ;
                     
					CardResult.cbCardCount = 4 + 2 ;
					CopyMemory(CardResult.cbResultCard, AnalyseResult.m_bFCardData + cbFourCardIndex, 4 ) ;
					CardResult.cbResultCard[4] = AnalyseResult.m_bSCardData[2] ;
					CardResult.cbResultCard[5] = AnalyseResult.m_bSCardData[3] ;
                    
					return true ;
				} 
				else if ( AnalyseResult.bFourCount >= 1 && AnalyseResult.bSignedCount == 5 )
				{ 
					BYTE cbFourCardIndex = ( AnalyseResult.bFourCount - 1 ) * 4 ;
                     
					CardResult.cbCardCount = 4 + 2 ;
					CopyMemory(CardResult.cbResultCard, AnalyseResult.m_bFCardData + cbFourCardIndex, 4 ) ;
					CardResult.cbResultCard[4] = AnalyseResult.m_bSCardData[3] ;
					CardResult.cbResultCard[5] = AnalyseResult.m_bSCardData[4] ;
                    
					return true ;
				}
			}
		}
	}
	return false ;
}

 
bool DDZCGameLogicSingle::TestOutAllCard( WORD wTestUser, BYTE cbWantOutCardData[], BYTE cbWantOutCardCount, bool bFirstOutCard ) {
    
	try {
		if ( ! VerifyOutCard( wTestUser, cbWantOutCardData, cbWantOutCardCount, m_cbAllCardData[ wTestUser ], m_cbUserCardCount[ wTestUser ], bFirstOutCard ) ) {
			return false;
		}
         
		if ( cbWantOutCardCount != m_cbUserCardCount[ wTestUser ] ) {
             
			m_StackHandCardInfo.InitStack();
			 
			tagHandCardInfo OriginHandCardInfo ;
             
			CopyMemory( OriginHandCardInfo.cbHandCardData, m_cbAllCardData[ wTestUser ], m_cbUserCardCount[ wTestUser ] );
			OriginHandCardInfo.cbHandCardCount = m_cbUserCardCount[ wTestUser ];
             
			RemoveCard( cbWantOutCardData, cbWantOutCardCount, OriginHandCardInfo.cbHandCardData, OriginHandCardInfo.cbHandCardCount );
			OriginHandCardInfo.cbHandCardCount -= cbWantOutCardCount;
             
			try {
				AnalyseOutCardType( OriginHandCardInfo.cbHandCardData, OriginHandCardInfo.cbHandCardCount, OriginHandCardInfo.CardTypeResult ) ;
			}
			catch( ... ) {
				return false ;
			}
             
			m_StackHandCardInfo.Push( &OriginHandCardInfo ); 
			long lJudgeCount = 0;
			while ( ! m_StackHandCardInfo.IsEmpty() ) {
                if ( ++lJudgeCount == 500 ) {
					
					return false;
				}
				 
				tagHandCardInfo *pTopHandCardInfo = NULL;
				m_StackHandCardInfo.GetTop( pTopHandCardInfo );
				 
				if ( pTopHandCardInfo == NULL ) {
					return false;
				}
				 
				tagOutCardTypeResult *pOutCardTypeResult = ( tagOutCardTypeResult * )pTopHandCardInfo->CardTypeResult;
				 
				pOutCardTypeResult[ CT_FOUR_LINE_TAKE_ONE ].cbCardTypeCount = 0;
				pOutCardTypeResult[ CT_FOUR_LINE_TAKE_TWO ].cbCardTypeCount = 0;
				 
				bool bBreakJudge = false;
				bool bFindLargestCard = false;
				for ( BYTE cbOutCardTypeIndx = CT_SINGLE; cbOutCardTypeIndx <= CT_MISSILE_CARD && ! bBreakJudge; ++cbOutCardTypeIndx ) {
					for ( BYTE cbHandCardIndx = 0; cbHandCardIndx < pOutCardTypeResult[ cbOutCardTypeIndx ].cbCardTypeCount && ! bBreakJudge ; ++cbHandCardIndx ) {
						 
						if ( pOutCardTypeResult[ cbOutCardTypeIndx ].cbEachHandCardCount[ cbHandCardIndx ] == 0 ) {
							continue;
						}
						 
						if ( IsLargestCard( wTestUser, pOutCardTypeResult[ cbOutCardTypeIndx ].cbCardData[ cbHandCardIndx ], pOutCardTypeResult[ cbOutCardTypeIndx ].cbEachHandCardCount[ cbHandCardIndx ] ) ) {
							 
							bool bIsLastHandCard = pOutCardTypeResult[ cbOutCardTypeIndx ].cbEachHandCardCount[ cbHandCardIndx ] == pTopHandCardInfo->cbHandCardCount ;
							if ( bIsLastHandCard ) {
								return true ;
							} 
							if ( ! VerifyOutCard( wTestUser, pOutCardTypeResult[ cbOutCardTypeIndx ].cbCardData[ cbHandCardIndx ],
												 pOutCardTypeResult[ cbOutCardTypeIndx ].cbEachHandCardCount[ cbHandCardIndx ], pTopHandCardInfo->cbHandCardData, pTopHandCardInfo->cbHandCardCount, bFirstOutCard ) ) {
								 
								pOutCardTypeResult[ cbOutCardTypeIndx ].cbEachHandCardCount[ cbHandCardIndx ] = 0;
								continue;
							}
							 
							tagHandCardInfo NewHandCardInfo ;
							 
							CopyMemory( NewHandCardInfo.cbHandCardData, pTopHandCardInfo->cbHandCardData, pTopHandCardInfo->cbHandCardCount );
							NewHandCardInfo.cbHandCardCount = pTopHandCardInfo->cbHandCardCount;
							 
							RemoveCard( pOutCardTypeResult[ cbOutCardTypeIndx ].cbCardData[ cbHandCardIndx ], pOutCardTypeResult[ cbOutCardTypeIndx ].cbEachHandCardCount[ cbHandCardIndx ],
									   NewHandCardInfo.cbHandCardData, NewHandCardInfo.cbHandCardCount );
							NewHandCardInfo.cbHandCardCount -= pOutCardTypeResult[ cbOutCardTypeIndx ].cbEachHandCardCount[ cbHandCardIndx ];
							 
							pOutCardTypeResult[ cbOutCardTypeIndx ].cbEachHandCardCount[ cbHandCardIndx ] = 0;
							 
							try {
								AnalyseOutCardType( NewHandCardInfo.cbHandCardData, NewHandCardInfo.cbHandCardCount, NewHandCardInfo.CardTypeResult ) ;
							}
							catch( ... ) {
								return false ;
							}
							 
							m_StackHandCardInfo.Push( & NewHandCardInfo );
							 
							bBreakJudge = true;
							 
							bFindLargestCard = true;
						} 
						else if (  pOutCardTypeResult[ cbOutCardTypeIndx ].cbEachHandCardCount[ cbHandCardIndx ] == pTopHandCardInfo->cbHandCardCount ) {
							return true ;
						}
					}
				}
				 
				if ( ! bFindLargestCard ) {
					m_StackHandCardInfo.Pop();
				}
			}
		}
		else {
			return true ;
		}
	}
	catch ( ... ) {
		return false;
	}
    
	return false ;
} 
bool DDZCGameLogicSingle::IsLargestCard( WORD wTestUser, BYTE const cbWantOutCardData[], BYTE const cbWantOutCardCount ) {
     
	WORD wFriendID = GAME_PLAYER ;
	if ( wTestUser != m_wBankerUser ) {
		wFriendID = ( wTestUser == ( ( m_wBankerUser + 1 ) % GAME_PLAYER ) ) ? ( m_wBankerUser + 2 ) % GAME_PLAYER :
        ( m_wBankerUser + 1 ) % GAME_PLAYER ;
	}
     
	try{
		for ( WORD wUser = 0; wUser < GAME_PLAYER; ++wUser ) {
			if ( wUser != wTestUser && wFriendID != wUser ) {
				tagOutCardTypeResult CardTypeResult[ 12 + 1 ] ;
				ZeroMemory( CardTypeResult, sizeof( CardTypeResult ) ) ;
                 
				try {
					AnalyseOutCardType( m_cbAllCardData[ wUser ], m_cbUserCardCount[ wUser ], cbWantOutCardData, cbWantOutCardCount, CardTypeResult ) ;
				}
				catch(...) {
					return false ;
				}
                
				for ( BYTE cbCardType = CT_SINGLE; cbCardType <= CT_MISSILE_CARD; ++cbCardType ) {
					if ( 0 < CardTypeResult[ cbCardType ].cbCardTypeCount ) {
						return false ;
					}
				}
			}
		}
	}
	catch( ... ) {
		return false ;
	}
    
	return true;
}
 
bool DDZCGameLogicSingle::VerifyOutCard( WORD wTestUser, BYTE const cbWantOutCardData[], BYTE const cbWantOutCardCount, BYTE const cbCurHandCardData[ MAX_COUNT ], BYTE const cbCurHandCardCount, bool bFirstOutCard )
{
     
	WORD wFriendID = GAME_PLAYER ;
	if ( wTestUser != m_wBankerUser ) {
		wFriendID = ( wTestUser == ( ( m_wBankerUser + 1 ) % GAME_PLAYER ) ) ? ( m_wBankerUser + 2 ) % GAME_PLAYER :
        ( m_wBankerUser + 1 ) % GAME_PLAYER ;
	}
    
	BYTE cbWantOutCardType = GetCardType( cbWantOutCardData, cbWantOutCardCount ) ;
     
	if ( bFirstOutCard && cbWantOutCardCount == cbCurHandCardCount ) {
		return true;
	}
     
	if ( ! IsLargestCard( wTestUser, cbWantOutCardData, cbWantOutCardCount ) ) {
		return false;
	}
     
	BYTE cbAllBombCard[ MAX_COUNT ], cbAllBombCount = 0 ;
	GetAllBomCard( cbCurHandCardData, cbCurHandCardCount, cbAllBombCard, cbAllBombCount ) ;
    
	if ( 0 < cbAllBombCount ) { 
		BYTE cbRemainCard [MAX_COUNT ], cbRemainCardCount ;
        
		CopyMemory( cbRemainCard, cbCurHandCardData, cbCurHandCardCount ) ;
		cbRemainCardCount = cbCurHandCardCount ;
        
		RemoveCard( cbWantOutCardData, cbWantOutCardCount, cbRemainCard, cbRemainCardCount ) ;
		cbRemainCardCount -= cbWantOutCardCount ;
         
		if ( CT_FOUR_LINE_TAKE_ONE == cbWantOutCardType || CT_FOUR_LINE_TAKE_TWO==cbWantOutCardType ) return false ;
         
		if ( CT_BOMB_CARD <= cbWantOutCardType && cbWantOutCardCount == cbCurHandCardCount ) return true ;
         
		if ( cbAllBombCount == m_cbUserCardCount[ wTestUser ] && CT_BOMB_CARD <= cbWantOutCardType ) return true ;
         
		if ( CT_BOMB_CARD <= cbWantOutCardType && GetCardType(cbRemainCard, cbRemainCardCount) != CT_ERROR &&
			CT_FOUR_LINE_TAKE_TWO != GetCardType( cbRemainCard, cbRemainCardCount ) && CT_FOUR_LINE_TAKE_ONE != GetCardType( cbRemainCard, cbRemainCardCount ) ) {
            return true ;
        }
         
        if (CT_BOMB_CARD <= cbWantOutCardType && bFirstOutCard ) {
           
            if ( wTestUser != m_wBankerUser && GetCardType( m_cbAllCardData[ m_wBankerUser ], m_cbUserCardCount[ m_wBankerUser ] ) == CT_ERROR ) {
                return false ;
            }
            
            WORD wUndersideOfBanker = (m_wBankerUser+1)%GAME_PLAYER ;	//ﾵ￘ￖ￷ￏￂﾼￒ
            WORD wUpsideOfBanker = (wUndersideOfBanker+1)%GAME_PLAYER ;	//ﾵ￘ￖ￷￉ￏﾼￒ
             
            if ( wTestUser == m_wBankerUser && GetCardType( m_cbAllCardData[ wUndersideOfBanker ], m_cbUserCardCount[ wUndersideOfBanker ] ) == CT_ERROR &&
                GetCardType( m_cbAllCardData[ wUpsideOfBanker ], m_cbUserCardCount[ wUpsideOfBanker ] ) == CT_ERROR ) {
                return false ;
            }
        }
         
        if ( cbWantOutCardType < CT_FOUR_LINE_TAKE_ONE && cbWantOutCardType != CT_SINGLE_LINE ) {
            for ( BYTE i = 0; i < cbWantOutCardCount; ++i )
                for ( BYTE j = 0; j < cbAllBombCount; ++j ) {
                    if ( GetCardValue( cbAllBombCard[ j ] ) == GetCardValue( cbWantOutCardData[ i ] ) ) return false ;
                }
        }
	}
     
	if ( cbCurHandCardCount == cbWantOutCardCount ) {
		return true ;
	}
    
    
	if ( cbCurHandCardCount == 0 ) {
		return true ;
	}
    
	try {
		if ( cbCurHandCardCount < cbWantOutCardCount ) {
			return false ;
		}
         
		BYTE cbRemainCard [MAX_COUNT], cbRemainCardCount ;
        
		CopyMemory( cbRemainCard, cbCurHandCardData, cbCurHandCardCount ) ;
		cbRemainCardCount = cbCurHandCardCount ;
        
		RemoveCard( cbWantOutCardData, cbWantOutCardCount, cbRemainCard, cbRemainCardCount ) ;
		cbRemainCardCount -= cbWantOutCardCount ;
        
		if ( cbRemainCardCount == 0 ) {
			return false;
		}
         
		if ( CT_THREE_LINE_TAKE_ONE <= cbWantOutCardType && cbWantOutCardType <= CT_FOUR_LINE_TAKE_TWO && ! bFirstOutCard ) {
			bool bHaveLargeCard = false ;
			for ( BYTE i = 3; i < cbWantOutCardCount; ++i )
				if ( 15 <= GetCardLogicValue( cbWantOutCardData[ i ]) ) {
					bHaveLargeCard = true ;
					break ;
				}
            if ( bHaveLargeCard ) {
                for ( BYTE i = 0; i < cbRemainCardCount; ++i ) {
                    if ( GetCardLogicValue( cbRemainCard[ i ]) < 15 ) {
                        return false ;
                    }
                }
            }
		}
	}
	catch(...) {
		return false ;
	}
    
	return true;
}
 
void DDZCGameLogicSingle::AnalyseOutCardType(BYTE const cbHandCardData[], BYTE const cbHandCardCount, tagOutCardTypeResult CardTypeResult[12+1])
{
	ZeroMemory(CardTypeResult, sizeof(CardTypeResult[0])*12) ;
	BYTE cbTmpCardData[MAX_COUNT] ; 
	BYTE cbReserveCardData[MAX_COUNT] ;
	CopyMemory(cbReserveCardData, cbHandCardData, cbHandCardCount) ;
	SortCardList(cbReserveCardData, cbHandCardCount, ST_ORDER) ;
	CopyMemory(cbTmpCardData, cbReserveCardData, cbHandCardCount) ;
     
	for(BYTE i=0; i<cbHandCardCount; ++i)
	{
		BYTE Index = CardTypeResult[CT_SINGLE].cbCardTypeCount ;
		CardTypeResult[CT_SINGLE].cbCardType = CT_SINGLE ;
		CardTypeResult[CT_SINGLE].cbCardData[Index][0] = cbTmpCardData[i] ;
		CardTypeResult[CT_SINGLE].cbEachHandCardCount[Index] = 1 ;
		CardTypeResult[CT_SINGLE].cbCardTypeCount++ ;
        
	}
     
	{
		BYTE m_bDCardData[MAX_COUNT] ;
		BYTE cbDoubleCardcount=0;
		GetAllDoubleCard(cbTmpCardData, cbHandCardCount, m_bDCardData, cbDoubleCardcount) ;
		for(BYTE i=0; i<cbDoubleCardcount; i+=2)
		{
			BYTE Index = CardTypeResult[CT_DOUBLE].cbCardTypeCount ;
			CardTypeResult[CT_DOUBLE].cbCardType = CT_DOUBLE ;
			CardTypeResult[CT_DOUBLE].cbCardData[Index][0] = m_bDCardData[i] ;
			CardTypeResult[CT_DOUBLE].cbCardData[Index][1] = m_bDCardData[i+1] ;
			CardTypeResult[CT_DOUBLE].cbEachHandCardCount[Index] = 2 ;
			CardTypeResult[CT_DOUBLE].cbCardTypeCount++ ;
		}
	}
    
	
    
    {
		BYTE m_bTCardData[MAX_COUNT];
		BYTE cbThreeCardCount=0 ;
		GetAllThreeCard(cbTmpCardData, cbHandCardCount, m_bTCardData, cbThreeCardCount) ;
		for(BYTE i=0; i<cbThreeCardCount; i+=3)
		{
			BYTE Index = CardTypeResult[CT_THREE].cbCardTypeCount ;
			CardTypeResult[CT_THREE].cbCardType = CT_THREE ;
			CardTypeResult[CT_THREE].cbCardData[Index][0] = m_bTCardData[i] ;
			CardTypeResult[CT_THREE].cbCardData[Index][1] = m_bTCardData[i+1] ;
			CardTypeResult[CT_THREE].cbCardData[Index][2] = m_bTCardData[i+2] ;
			CardTypeResult[CT_THREE].cbEachHandCardCount[Index] = 3 ;
			CardTypeResult[CT_THREE].cbCardTypeCount++ ;
		}
	}
     
	{
		BYTE m_bFCardData[MAX_COUNT];
		BYTE cbFourCardCount=0 ;
		if(cbHandCardCount>=2 && 0x4F==cbTmpCardData[0] && 0x4E==cbTmpCardData[1])
		{
			BYTE Index = CardTypeResult[CT_BOMB_CARD].cbCardTypeCount ;
			CardTypeResult[CT_BOMB_CARD].cbCardType = CT_BOMB_CARD ;
			CardTypeResult[CT_BOMB_CARD].cbCardData[Index][0] = cbTmpCardData[0] ;
			CardTypeResult[CT_BOMB_CARD].cbCardData[Index][1] = cbTmpCardData[1] ;
			CardTypeResult[CT_BOMB_CARD].cbEachHandCardCount[Index] = 2 ;
			CardTypeResult[CT_BOMB_CARD].cbCardTypeCount++ ;
			GetAllBomCard(cbTmpCardData+2, cbHandCardCount-2, m_bFCardData, cbFourCardCount) ;
		}
		else GetAllBomCard(cbTmpCardData, cbHandCardCount, m_bFCardData, cbFourCardCount) ;
		for (BYTE i=0; i<cbFourCardCount; i+=4)
		{
			BYTE Index = CardTypeResult[CT_BOMB_CARD].cbCardTypeCount ;
			CardTypeResult[CT_BOMB_CARD].cbCardType = CT_BOMB_CARD ;
			CardTypeResult[CT_BOMB_CARD].cbCardData[Index][0] = m_bFCardData[i] ;
			CardTypeResult[CT_BOMB_CARD].cbCardData[Index][1] = m_bFCardData[i+1] ;
			CardTypeResult[CT_BOMB_CARD].cbCardData[Index][2] = m_bFCardData[i+2] ;
			CardTypeResult[CT_BOMB_CARD].cbCardData[Index][3] = m_bFCardData[i+3] ;
			CardTypeResult[CT_BOMB_CARD].cbEachHandCardCount[Index] = 4 ;
			CardTypeResult[CT_BOMB_CARD].cbCardTypeCount++ ;
		}
	}
    
    
	{ 
		CopyMemory(cbTmpCardData, cbReserveCardData, cbHandCardCount) ;
        
		BYTE cbFirstCard = 0 ; 
		for(BYTE i=0 ; i<cbHandCardCount ; ++i)
		{
			if(GetCardLogicValue(cbTmpCardData[i])<15)
			{
				cbFirstCard = i ;
				break ;
			}
		}
        
		BYTE cbSingleLineCard[12] ;
		BYTE cbSingleLineCount=1 ;
		BYTE cbLeftCardCount = cbHandCardCount ;
		bool bFindSingleLine = true ;
         
		while (cbLeftCardCount>=5 && bFindSingleLine)
		{
			cbSingleLineCount=1 ;
			bFindSingleLine = false ;
			BYTE cbLastCard = cbTmpCardData[cbFirstCard] ;
			cbSingleLineCard[cbSingleLineCount-1] = cbTmpCardData[cbFirstCard] ;
			for (BYTE i=cbFirstCard+1; i<cbLeftCardCount; i++)
			{
				BYTE cbCardData=cbTmpCardData[i];
                 
				if (1!=(GetCardLogicValue(cbLastCard)-GetCardLogicValue(cbCardData)) && GetCardValue(cbLastCard)!=GetCardValue(cbCardData))
				{
					cbLastCard = cbTmpCardData[i] ; 
					if(cbSingleLineCount<5)
					{
						cbSingleLineCount = 1 ;
						cbSingleLineCard[cbSingleLineCount-1] = cbTmpCardData[i] ;
						continue ;
					}
					else break ;
				} 
				else if(GetCardValue(cbLastCard)!=GetCardValue(cbCardData))
				{
					cbLastCard = cbCardData ;
					cbSingleLineCard[cbSingleLineCount] = cbCardData ;
					++cbSingleLineCount ;
				}
			}
            
			if(cbSingleLineCount>=5)
			{
				BYTE Index ;
                
				int nStart = 0 ;
                
				nStart = cbSingleLineCount - 5 ;
				while ( 0 < nStart )
				{
					Index = CardTypeResult[CT_SINGLE_LINE].cbCardTypeCount ;
					BYTE cbThisLineCount = cbSingleLineCount-nStart ;
					CardTypeResult[CT_SINGLE_LINE].cbCardType = CT_SINGLE_LINE ;
					CopyMemory(CardTypeResult[CT_SINGLE_LINE].cbCardData[Index], cbSingleLineCard, sizeof(BYTE)*(cbThisLineCount));
					CardTypeResult[CT_SINGLE_LINE].cbEachHandCardCount[Index] = cbThisLineCount;
					CardTypeResult[CT_SINGLE_LINE].cbCardTypeCount++ ;
					nStart-- ;
				}
                
				nStart = cbSingleLineCount - 5;
				while ( 0 <= nStart )
				{
					Index = CardTypeResult[CT_SINGLE_LINE].cbCardTypeCount ;
					BYTE cbThisLineCount = cbSingleLineCount-nStart ;
					CardTypeResult[CT_SINGLE_LINE].cbCardType = CT_SINGLE_LINE ;
					CopyMemory(CardTypeResult[CT_SINGLE_LINE].cbCardData[Index], cbSingleLineCard+nStart, sizeof(BYTE)*(cbThisLineCount));
					CardTypeResult[CT_SINGLE_LINE].cbEachHandCardCount[Index] = cbThisLineCount;
					CardTypeResult[CT_SINGLE_LINE].cbCardTypeCount++ ;
					nStart-- ;
				}
                
				RemoveCard(cbSingleLineCard, cbSingleLineCount, cbTmpCardData, cbLeftCardCount) ;
				cbLeftCardCount -= cbSingleLineCount ;
				bFindSingleLine = true ;
			}
		}
        
	}
    
	{
		CopyMemory(cbTmpCardData, cbReserveCardData, cbHandCardCount) ;
        
		BYTE cbFirstCard = 0 ;
		for(BYTE i=0 ; i<cbHandCardCount ; ++i)	if(GetCardLogicValue(cbTmpCardData[i])<15)	{cbFirstCard = i ; break ;}
        
		BYTE cbLeftCardCount = cbHandCardCount-cbFirstCard ;
		bool bFindDoubleLine = true ;
		BYTE cbDoubleLineCount = 0 ;
		BYTE cbDoubleLineCard[24] ;
		while (cbLeftCardCount>=6 && bFindDoubleLine)
		{
			BYTE cbLastCard = cbTmpCardData[cbFirstCard] ;
			BYTE cbSameCount = 1 ;
			cbDoubleLineCount = 0 ;
			bFindDoubleLine=false ;
			for(BYTE i=cbFirstCard+1 ; i<cbLeftCardCount+cbFirstCard ; ++i)
			{
				while (GetCardLogicValue(cbLastCard)==GetCardLogicValue(cbTmpCardData[i]) && i<cbLeftCardCount+cbFirstCard)
				{
					++cbSameCount;
					++i ;
				}
                
				BYTE cbLastDoubleCardValue ;
				if(cbDoubleLineCount>0) cbLastDoubleCardValue = GetCardLogicValue(cbDoubleLineCard[cbDoubleLineCount-1]) ;
				if((cbSameCount<2 || (cbDoubleLineCount>0 && (cbLastDoubleCardValue-GetCardLogicValue(cbLastCard))!=1)) && i<=cbLeftCardCount+cbFirstCard)
				{
					if(cbDoubleLineCount>=6) break ;
					if(cbSameCount>=2) i-=cbSameCount ;
					cbLastCard = cbTmpCardData[i] ;
					cbDoubleLineCount = 0 ;
				}
				else if(cbSameCount>=2)
				{
					cbDoubleLineCard[cbDoubleLineCount] = cbTmpCardData[i-cbSameCount] ;
					cbDoubleLineCard[cbDoubleLineCount+1] = cbTmpCardData[i-cbSameCount+1] ;
					cbDoubleLineCount += 2 ;
                    
					if(i==(cbLeftCardCount+cbFirstCard-2))
						if((GetCardLogicValue(cbLastCard)-GetCardLogicValue(cbTmpCardData[i]))==1 && (GetCardLogicValue(cbTmpCardData[i])==GetCardLogicValue(cbTmpCardData[i+1])))
						{
							cbDoubleLineCard[cbDoubleLineCount] = cbTmpCardData[i] ;
							cbDoubleLineCard[cbDoubleLineCount+1] = cbTmpCardData[i+1] ;
							cbDoubleLineCount += 2 ;
							break ;
						}
                    
				}
                
				cbLastCard = cbTmpCardData[i] ;
				cbSameCount = 1 ;
			}
            
			if(cbDoubleLineCount>=6)
			{
				BYTE Index ;
                
				BYTE cbCurrentDoubleLineCount = 6 ;
				while ( cbCurrentDoubleLineCount < cbDoubleLineCount )
				{
					Index = CardTypeResult[CT_DOUBLE_LINE].cbCardTypeCount ;
					CardTypeResult[CT_DOUBLE_LINE].cbCardType = CT_DOUBLE_LINE ;
					CopyMemory(CardTypeResult[CT_DOUBLE_LINE].cbCardData[Index], cbDoubleLineCard, sizeof(BYTE)*cbCurrentDoubleLineCount);
					CardTypeResult[CT_DOUBLE_LINE].cbEachHandCardCount[Index] = cbCurrentDoubleLineCount;
					CardTypeResult[CT_DOUBLE_LINE].cbCardTypeCount++ ;
                    
					cbCurrentDoubleLineCount += 2 ;
				}
                
				if ( cbDoubleLineCount >= 6 )
				{
					int cbLeftLen = cbDoubleLineCount - 6 ;
					while ( cbLeftLen >= 0 )
					{
						Index = CardTypeResult[CT_DOUBLE_LINE].cbCardTypeCount ;
						CardTypeResult[CT_DOUBLE_LINE].cbCardType = CT_DOUBLE_LINE ;
						CopyMemory(CardTypeResult[CT_DOUBLE_LINE].cbCardData[Index], cbDoubleLineCard + cbLeftLen, sizeof( BYTE ) * ( cbDoubleLineCount - cbLeftLen ));
						CardTypeResult[CT_DOUBLE_LINE].cbEachHandCardCount[Index] = cbDoubleLineCount - cbLeftLen;
						CardTypeResult[CT_DOUBLE_LINE].cbCardTypeCount++ ;
                        
						cbLeftLen -= 2 ;
					}
				}
                
				RemoveCard(cbDoubleLineCard, cbDoubleLineCount, cbTmpCardData, cbFirstCard+cbLeftCardCount) ;
				bFindDoubleLine=true ;
				cbLeftCardCount -= cbDoubleLineCount ;
			}
		}
	}
    
	{
		CopyMemory(cbTmpCardData, cbReserveCardData, cbHandCardCount) ;
        
		BYTE cbFirstCard = 0 ;
		for(BYTE i=0 ; i<cbHandCardCount ; ++i)	if(GetCardLogicValue(cbTmpCardData[i])<15)	{cbFirstCard = i ; break ;}
        
		BYTE cbLeftCardCount = cbHandCardCount-cbFirstCard ;
		bool bFindThreeLine = true ;
		BYTE cbThreeLineCount = 0 ;
		BYTE cbThreeLineCard[20] ;
		while (cbLeftCardCount>=6 && bFindThreeLine)
		{
			BYTE cbLastCard = cbTmpCardData[cbFirstCard] ;
			BYTE cbSameCount = 1 ;
			cbThreeLineCount = 0 ;
			bFindThreeLine = false ;
			for(BYTE i=cbFirstCard+1 ; i<cbLeftCardCount+cbFirstCard ; ++i)
			{
				while (GetCardLogicValue(cbLastCard)==GetCardLogicValue(cbTmpCardData[i]) && i<cbLeftCardCount+cbFirstCard)
				{
					++cbSameCount;
					++i ;
				}
                
				BYTE cbLastThreeCardValue ;
				if(cbThreeLineCount>0) cbLastThreeCardValue = GetCardLogicValue(cbThreeLineCard[cbThreeLineCount-1]) ;
                
				if((cbSameCount<3 || (cbThreeLineCount>0&&(cbLastThreeCardValue-GetCardLogicValue(cbLastCard))!=1)) && i<=cbLeftCardCount+cbFirstCard)
				{
					if(cbThreeLineCount>=6) break ;
                    
					if(cbSameCount>=3) i-=cbSameCount ;
					cbLastCard = cbTmpCardData[i] ;
					cbThreeLineCount = 0 ;
				}
				else if(cbSameCount>=3)
				{
					cbThreeLineCard[cbThreeLineCount] = cbTmpCardData[i-cbSameCount] ;
					cbThreeLineCard[cbThreeLineCount+1] = cbTmpCardData[i-cbSameCount+1] ;
					cbThreeLineCard[cbThreeLineCount+2] = cbTmpCardData[i-cbSameCount+2] ;
					cbThreeLineCount += 3 ;
                    
					if(i==(cbLeftCardCount+cbFirstCard-3))
						if((GetCardLogicValue(cbLastCard)-GetCardLogicValue(cbTmpCardData[i]))==1 && (GetCardLogicValue(cbTmpCardData[i])==GetCardLogicValue(cbTmpCardData[i+1])) && (GetCardLogicValue(cbTmpCardData[i])==GetCardLogicValue(cbTmpCardData[i+2])))
						{
							cbThreeLineCard[cbThreeLineCount] = cbTmpCardData[i] ;
							cbThreeLineCard[cbThreeLineCount+1] = cbTmpCardData[i+1] ;
							cbThreeLineCard[cbThreeLineCount+2] = cbTmpCardData[i+2] ;
							cbThreeLineCount += 3 ;
							break ;
						}
                    
				}
                
				cbLastCard = cbTmpCardData[i] ;
				cbSameCount = 1 ;
			}
            
			if(cbThreeLineCount>=6)
			{
				BYTE Index ;
                
				Index = CardTypeResult[CT_THREE_LINE].cbCardTypeCount ;
				CardTypeResult[CT_THREE_LINE].cbCardType = CT_THREE_LINE ;
				CopyMemory(CardTypeResult[CT_THREE_LINE].cbCardData[Index], cbThreeLineCard, sizeof(BYTE)*cbThreeLineCount);
				CardTypeResult[CT_THREE_LINE].cbEachHandCardCount[Index] = cbThreeLineCount;
				CardTypeResult[CT_THREE_LINE].cbCardTypeCount++ ;
                
				RemoveCard(cbThreeLineCard, cbThreeLineCount, cbTmpCardData, cbFirstCard+cbLeftCardCount) ;
				bFindThreeLine=true ;
				cbLeftCardCount -= cbThreeLineCount ;
			}
		}
        
	}
	{
		CopyMemory(cbTmpCardData, cbReserveCardData, cbHandCardCount) ;
        
		BYTE cbHandThreeCard[MAX_COUNT];
		BYTE cbHandThreeCount=0 ;
        
		BYTE cbAllBomCardData[MAX_COUNT] ;
		BYTE cbAllBomCardCount=0 ;
		GetAllBomCard(cbTmpCardData, cbHandCardCount, cbAllBomCardData, cbAllBomCardCount) ;
		RemoveCard(cbAllBomCardData, cbAllBomCardCount, cbTmpCardData, cbHandCardCount) ;
        
		GetAllThreeCard(cbTmpCardData, cbHandCardCount-cbAllBomCardCount, cbHandThreeCard, cbHandThreeCount) ;
        
		{
			BYTE Index ;
			BYTE cbRemainCardData[MAX_COUNT] ;
			CopyMemory(cbRemainCardData, cbTmpCardData, cbHandCardCount-cbAllBomCardCount) ;
			BYTE cbRemainCardCount=cbHandCardCount-cbAllBomCardCount-cbHandThreeCount ;
			RemoveCard(cbHandThreeCard, cbHandThreeCount, cbRemainCardData, cbHandCardCount-cbAllBomCardCount) ;
	
			for(BYTE i=0; i<cbHandThreeCount; i+=3)
			{
                
				for(BYTE j=0; j<cbRemainCardCount; ++j)
				{
					Index = CardTypeResult[CT_THREE_LINE_TAKE_ONE].cbCardTypeCount ;
					CardTypeResult[CT_THREE_LINE_TAKE_ONE].cbCardType = CT_THREE_LINE_TAKE_ONE ;
					CardTypeResult[CT_THREE_LINE_TAKE_ONE].cbCardData[Index][0] = cbHandThreeCard[i] ;
					CardTypeResult[CT_THREE_LINE_TAKE_ONE].cbCardData[Index][1] = cbHandThreeCard[i+1] ;
					CardTypeResult[CT_THREE_LINE_TAKE_ONE].cbCardData[Index][2] = cbHandThreeCard[i+2] ;
					CardTypeResult[CT_THREE_LINE_TAKE_ONE].cbCardData[Index][3] = cbRemainCardData[j] ;
					CardTypeResult[CT_THREE_LINE_TAKE_ONE].cbEachHandCardCount[Index] = 4 ;
					CardTypeResult[CT_THREE_LINE_TAKE_ONE].cbCardTypeCount++ ;
				}
			}
		}
         
		BYTE cbLeftThreeCardCount=cbHandThreeCount ;
		bool bFindThreeLine=true ;
		BYTE cbLastIndex=0 ;
		if(GetCardLogicValue(cbHandThreeCard[0])==15) cbLastIndex=3 ;
		while (cbLeftThreeCardCount>=6 && bFindThreeLine)
		{
			BYTE cbLastLogicCard=GetCardLogicValue(cbHandThreeCard[cbLastIndex]);
			BYTE cbThreeLineCard[MAX_COUNT];
			BYTE cbThreeLineCardCount=3;
			cbThreeLineCard[0]=cbHandThreeCard[cbLastIndex];
			cbThreeLineCard[1]=cbHandThreeCard[cbLastIndex+1];
			cbThreeLineCard[2]=cbHandThreeCard[cbLastIndex+2];
            
			bFindThreeLine = false ;
			for(BYTE j=3+cbLastIndex; j<cbLeftThreeCardCount; j+=3)
			{ 
				if(1!=(cbLastLogicCard-(GetCardLogicValue(cbHandThreeCard[j]))))
				{
					cbLastIndex = j ;
					if(cbLeftThreeCardCount-j>=6) bFindThreeLine = true ;
                    
					break;
				}
                
				cbLastLogicCard=GetCardLogicValue(cbHandThreeCard[j]);
				cbThreeLineCard[cbThreeLineCardCount]=cbHandThreeCard[j];
				cbThreeLineCard[cbThreeLineCardCount+1]=cbHandThreeCard[j+1];
				cbThreeLineCard[cbThreeLineCardCount+2]=cbHandThreeCard[j+2];
				cbThreeLineCardCount += 3;
			}
			if(cbThreeLineCardCount>3)
			{
				BYTE Index ;
                
				BYTE cbRemainCard[MAX_COUNT];
				BYTE cbRemainCardCount=cbHandCardCount-cbAllBomCardCount-cbHandThreeCount ;
                
                 
				CopyMemory(cbRemainCard, cbTmpCardData, (cbHandCardCount-cbAllBomCardCount)*sizeof(BYTE));
				RemoveCard(cbHandThreeCard, cbHandThreeCount, cbRemainCard, cbHandCardCount-cbAllBomCardCount) ;
                
				for(BYTE start=0; start<cbThreeLineCardCount-3; start+=3)
				{ 
					BYTE cbThisTreeLineCardCount = cbThreeLineCardCount-start ; 
					BYTE cbSingleCardCount=(cbThisTreeLineCardCount)/3;
                     
					if(cbRemainCardCount<cbSingleCardCount) continue ;
                     
					BYTE cbComCard[5];
					BYTE cbComResCard[254][5] ;
					BYTE cbComResLen=0 ;
                    
					Combination(cbComCard, 0, cbComResCard, cbComResLen, cbRemainCard, cbSingleCardCount, cbRemainCardCount, cbSingleCardCount);
					for(BYTE i=0; i<cbComResLen; ++i)
					{
						Index = CardTypeResult[CT_THREE_LINE_TAKE_ONE].cbCardTypeCount ;
						CardTypeResult[CT_THREE_LINE_TAKE_ONE].cbCardType = CT_THREE_LINE_TAKE_ONE ; 
						CopyMemory(CardTypeResult[CT_THREE_LINE_TAKE_ONE].cbCardData[Index], cbThreeLineCard+start, sizeof(BYTE)*cbThisTreeLineCardCount); 
						CopyMemory(CardTypeResult[CT_THREE_LINE_TAKE_ONE].cbCardData[Index]+cbThisTreeLineCardCount, cbComResCard[i], cbSingleCardCount) ;
                        
                        
						CardTypeResult[CT_THREE_LINE_TAKE_ONE].cbEachHandCardCount[Index] = cbThisTreeLineCardCount+cbSingleCardCount ;
						CardTypeResult[CT_THREE_LINE_TAKE_ONE].cbCardTypeCount++ ;
					}
                    
				}
                 
				bFindThreeLine = true ;
				RemoveCard(cbThreeLineCard, cbThreeLineCardCount, cbHandThreeCard, cbLeftThreeCardCount) ;
				cbLeftThreeCardCount -= cbThreeLineCardCount ;
			}
		}
	}
     
	{ 
		CopyMemory(cbTmpCardData, cbReserveCardData, cbHandCardCount) ;
        
		BYTE cbHandThreeCard[MAX_COUNT];
		BYTE cbHandThreeCount=0 ;
		BYTE cbRemainCarData[MAX_COUNT] ;
		BYTE cbRemainCardCount=0 ;
         
		GetAllThreeCard(cbTmpCardData, cbHandCardCount, cbHandThreeCard, cbHandThreeCount) ;
         
		CopyMemory(cbRemainCarData, cbTmpCardData, cbHandCardCount) ;
		RemoveCard(cbHandThreeCard, cbHandThreeCount, cbRemainCarData, cbHandCardCount) ;
		cbRemainCardCount = cbHandCardCount-cbHandThreeCount ;
         
		BYTE cbAllDoubleCardData[MAX_COUNT] ;
		BYTE cbAllDoubleCardCount=0 ;
		GetAllDoubleCard(cbRemainCarData, cbRemainCardCount, cbAllDoubleCardData, cbAllDoubleCardCount) ;
         
		for(BYTE i=0; i<cbHandThreeCount; i+=3)
		{
			BYTE Index ;
             
			for(BYTE j=0; j<cbAllDoubleCardCount; j+=2)
			{
				Index = CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbCardTypeCount ;
				CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbCardType = CT_THREE_LINE_TAKE_TWO ;
				CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbCardData[Index][0] = cbHandThreeCard[i] ;
				CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbCardData[Index][1] = cbHandThreeCard[i+1] ;
				CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbCardData[Index][2] = cbHandThreeCard[i+2] ;
				CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbCardData[Index][3] = cbAllDoubleCardData[j] ;
				CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbCardData[Index][4] = cbAllDoubleCardData[j+1] ;
				CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbEachHandCardCount[Index] = 5 ;
				CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbCardTypeCount++ ;
			}
		}
         
		BYTE cbLeftThreeCardCount=cbHandThreeCount ;
		bool bFindThreeLine=true ;
		BYTE cbLastIndex=0 ;
		if(GetCardLogicValue(cbHandThreeCard[0])==15) cbLastIndex=3 ;
		while (cbLeftThreeCardCount>=6 && bFindThreeLine)
		{
			BYTE cbLastLogicCard=GetCardLogicValue(cbHandThreeCard[cbLastIndex]);
			BYTE cbThreeLineCard[MAX_COUNT];
			BYTE cbThreeLineCardCount=3;
			cbThreeLineCard[0]=cbHandThreeCard[cbLastIndex];
			cbThreeLineCard[1]=cbHandThreeCard[cbLastIndex+1];
			cbThreeLineCard[2]=cbHandThreeCard[cbLastIndex+2];
            
			bFindThreeLine=false ;
			for(BYTE j=3+cbLastIndex; j<cbLeftThreeCardCount; j+=3)
			{ 
				if(1!=(cbLastLogicCard-(GetCardLogicValue(cbHandThreeCard[j]))))
				{
					cbLastIndex = j ;
					if(cbLeftThreeCardCount-j>=6) bFindThreeLine = true ;
                    
					break;
				}
                
				cbLastLogicCard=GetCardLogicValue(cbHandThreeCard[j]);
				cbThreeLineCard[cbThreeLineCardCount]=cbHandThreeCard[j];
				cbThreeLineCard[cbThreeLineCardCount+1]=cbHandThreeCard[j+1];
				cbThreeLineCard[cbThreeLineCardCount+2]=cbHandThreeCard[j+2];
				cbThreeLineCardCount += 3;
			}
			if(cbThreeLineCardCount>3)
			{
				BYTE Index ;
                
				for(BYTE start=0; start<cbThreeLineCardCount-3; start+=3)
				{ 
					BYTE cbThisTreeLineCardCount = cbThreeLineCardCount-start ; 
					BYTE cbDoubleCardCount=((cbThisTreeLineCardCount)/3);
                     
					if(cbRemainCardCount<cbDoubleCardCount) continue ;
                    
					BYTE cbDoubleCardIndex[10]; 
					for(BYTE i=0, j=0; i<cbAllDoubleCardCount; i+=2, ++j)
						cbDoubleCardIndex[j]=i ;
                     
					BYTE cbComCard[5];
					BYTE cbComResCard[254][5] ;
					BYTE cbComResLen=0 ;
                     
					Combination(cbComCard, 0, cbComResCard, cbComResLen, cbDoubleCardIndex, cbDoubleCardCount, cbAllDoubleCardCount/2, cbDoubleCardCount);
                    
					for(BYTE i=0; i<cbComResLen; ++i)
					{
						Index = CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbCardTypeCount ;
						CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbCardType = CT_THREE_LINE_TAKE_TWO ; 
						CopyMemory(CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbCardData[Index], cbThreeLineCard+start, sizeof(BYTE)*cbThisTreeLineCardCount);
						for(BYTE j=0, k=0; j<cbDoubleCardCount; ++j, k+=2)
						{
							CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbCardData[Index][cbThisTreeLineCardCount+k] = cbAllDoubleCardData[cbComResCard[i][j]];
							CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbCardData[Index][cbThisTreeLineCardCount+k+1] = cbAllDoubleCardData[cbComResCard[i][j]+1];
						}
                        
						CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbEachHandCardCount[Index] = cbThisTreeLineCardCount+2*cbDoubleCardCount ;
						CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbCardTypeCount++ ;
                        
					}
                    
				} 
				bFindThreeLine = true ;
				RemoveCard(cbThreeLineCard, cbThreeLineCardCount, cbHandThreeCard, cbLeftThreeCardCount) ;
				cbLeftThreeCardCount -= cbThreeLineCardCount ;
			}
		}
	}
    
}






void DDZCGameLogicSingle::SetUserCard(WORD wChairID, BYTE cbCardData[], BYTE cbCardCount)
{
	CopyMemory(m_cbAllCardData[wChairID], cbCardData, cbCardCount*sizeof(BYTE)) ;
	m_cbUserCardCount[wChairID] = cbCardCount ;
    
	SortCardList(m_cbAllCardData[wChairID], cbCardCount, ST_ORDER) ;
    
}

void DDZCGameLogicSingle::SetBackCard(WORD wChairID, BYTE cbBackCardData[], BYTE cbCardCount)
{
	BYTE cbTmpCount = m_cbUserCardCount[wChairID] ;
	CopyMemory(m_cbAllCardData[wChairID]+cbTmpCount, cbBackCardData, cbCardCount*sizeof(BYTE)) ;
	m_cbUserCardCount[wChairID] += cbCardCount ;
    
	SortCardList(m_cbAllCardData[wChairID], m_cbUserCardCount[wChairID], ST_ORDER) ;
    
	for (int chairID=0;chairID<GAME_PLAYER;chairID++)
	{
		for (int num=0;num<m_cbUserCardCount[wChairID];num++)
		{
			printf("%d  ",GetCardValue(m_cbAllCardData[chairID][num]));
			//printf("m_cbAllCardData[%d][%d]=%d  ",chairID,num,GetCardValue(m_cbAllCardData[chairID][num]));
		}
		printf("\n");
	}
}

void DDZCGameLogicSingle::SetBanker(WORD wBanker)
{
	m_wBankerUser = wBanker ;
	m_lBankerOutCardCount = 0 ;
}
void DDZCGameLogicSingle::SetLandScoreCardData(BYTE cbCardData[], BYTE cbCardCount)
{
	if(cbCardCount!=MAX_COUNT) return ;
    
	CopyMemory(m_cbLandScoreCardData, cbCardData, cbCardCount*sizeof(BYTE)) ;
    
	SortCardList(m_cbLandScoreCardData, cbCardCount, ST_ORDER) ;
}
void DDZCGameLogicSingle::RemoveUserCardData(WORD wChairID, BYTE cbRemoveCardData[], BYTE cbRemoveCardCount)
{
	bool bSuccess = RemoveCard(cbRemoveCardData, cbRemoveCardCount, m_cbAllCardData[wChairID], m_cbUserCardCount[wChairID]) ;
	m_cbUserCardCount[wChairID] -= cbRemoveCardCount ;
    
}
void DDZCGameLogicSingle::BankerOutCard(const BYTE cbHandCardData[], BYTE cbHandCardCount, tagOutCardResult & OutCardResult)
{
	tagOutCardTypeResult CardTypeResult[12+1] ;
	ZeroMemory(CardTypeResult, sizeof(CardTypeResult)) ;
    
	ZeroMemory(&OutCardResult, sizeof(OutCardResult)) ;
    
	BYTE cbLineCard[MAX_COUNT] ;
	BYTE cbThreeLineCard[MAX_COUNT] ;
	BYTE cbDoubleLineCard[MAX_COUNT] ;
	BYTE cbLineCardCount;
	BYTE cbThreeLineCardCount ;
	BYTE cbDoubleLineCount ;
	GetAllLineCard(cbHandCardData, cbHandCardCount, cbLineCard, cbLineCardCount) ;
	GetAllThreeCard(cbHandCardData, cbHandCardCount, cbThreeLineCard, cbThreeLineCardCount) ;
	GetAllDoubleCard(cbHandCardData, cbHandCardCount, cbDoubleLineCard, cbDoubleLineCount) ;
    
	WORD wUndersideOfBanker = (m_wBankerUser+1)%GAME_PLAYER ;
	WORD wUpsideOfBanker = (wUndersideOfBanker+1)%GAME_PLAYER ;
    
	BYTE cbSingleCardCount = MAX_COUNT+CT_MISSILE_CARD ;
	bool bFindBestCard = false ;
	AnalyseOutCardType(cbHandCardData, cbHandCardCount, CardTypeResult) ;
	for(BYTE cbCardType=CT_SINGLE; cbCardType<=CT_MISSILE_CARD; ++cbCardType)
		if(CardTypeResult[cbCardType].cbCardTypeCount>0)
		{
			for(long lIndex=0; lIndex<CardTypeResult[cbCardType].cbCardTypeCount; ++lIndex)
			{
				if(TestOutAllCard(m_wBankerUser, CardTypeResult[cbCardType].cbCardData[lIndex], CardTypeResult[cbCardType].cbEachHandCardCount[lIndex], true))
				{
					BYTE cbTmpSingleCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, CardTypeResult[cbCardType].cbCardData[lIndex],
                                                                  CardTypeResult[cbCardType].cbEachHandCardCount[lIndex]) ;
                    
					if (cbTmpSingleCount >= MAX_COUNT) continue ;
                    
					BYTE cbBombCardType = GetCardType(CardTypeResult[cbCardType].cbCardData[lIndex], CardTypeResult[cbCardType].cbEachHandCardCount[lIndex]) ;
					if (cbBombCardType == CT_BOMB_CARD) cbTmpSingleCount += 4;
					else if (cbBombCardType == CT_MISSILE_CARD) cbTmpSingleCount += 5;
					else if ( 15 == GetCardLogicValue( CardTypeResult[ cbCardType ].cbCardData[ lIndex ][ 0 ] ) ) cbTmpSingleCount += 2;
					else if ( 15 < GetCardLogicValue( CardTypeResult[ cbCardType ].cbCardData[ lIndex ][ 0 ] ) ) cbTmpSingleCount += 3;
                    
                    
					if (cbTmpSingleCount <= cbSingleCardCount)
					{
						OutCardResult.cbCardCount=CardTypeResult[cbCardType].cbEachHandCardCount[lIndex];
						CopyMemory(OutCardResult.cbResultCard, CardTypeResult[cbCardType].cbCardData[lIndex],
                                   CardTypeResult[cbCardType].cbEachHandCardCount[lIndex]*sizeof(BYTE));
						cbSingleCardCount = cbTmpSingleCount ;
						bFindBestCard = true ;
					}
                    
				}
			}
		}
    if (bFindBestCard) return ;
    
    if ( cbHandCardCount == 4 && GetCardLogicValue(cbHandCardData[1]) == 16 && m_cbUserCardCount[wUndersideOfBanker] == 1 &&
        GetCardLogicValue(cbHandCardData[2]) < GetCardLogicValue(m_cbAllCardData[wUndersideOfBanker][0]))
    {
        OutCardResult.cbCardCount = 1 ;
        OutCardResult.cbResultCard[0] = cbHandCardData[2] ;
        return ;
    }
    
    if ( AnalyseFourCardType(cbHandCardData, cbHandCardCount, m_cbAllCardData[wUndersideOfBanker], m_cbUserCardCount[wUndersideOfBanker], OutCardResult ) )
    {
        return ;
    }
    
    if ( cbHandCardCount == 4 && GetCardLogicValue(cbHandCardData[1]) == 16 && m_cbUserCardCount[wUpsideOfBanker] == 1 &&
        GetCardLogicValue(cbHandCardData[2]) < GetCardLogicValue(m_cbAllCardData[wUpsideOfBanker][0]))
    {
        OutCardResult.cbCardCount = 1 ;
        OutCardResult.cbResultCard[0] = cbHandCardData[2] ;
        return ;
    }
    if ( AnalyseFourCardType(cbHandCardData, cbHandCardCount, m_cbAllCardData[wUpsideOfBanker], m_cbUserCardCount[wUpsideOfBanker], OutCardResult ) )
    {
        return ;
    }
    {
        if(cbLineCardCount+1==cbHandCardCount && CT_SINGLE==GetCardType(cbLineCard, cbLineCardCount))
        {
            OutCardResult.cbCardCount = cbLineCardCount ;
            CopyMemory(OutCardResult.cbResultCard, cbLineCard, cbLineCardCount) ;
        }
        else if(cbThreeLineCardCount+1==cbHandCardCount && CT_THREE_LINE==GetCardType(cbThreeLineCard, cbThreeLineCardCount))
        {
            OutCardResult.cbCardCount = cbThreeLineCardCount ;
            CopyMemory(OutCardResult.cbResultCard, cbThreeLineCard, cbThreeLineCardCount) ;
        }
        else if(cbDoubleLineCount+1==cbHandCardCount && CT_DOUBLE_LINE==GetCardType(cbDoubleLineCard, cbDoubleLineCount))
        {
            OutCardResult.cbCardCount = cbDoubleLineCount ;
            CopyMemory(OutCardResult.cbResultCard, cbDoubleLineCard, cbDoubleLineCount) ;
        }
        else if(cbHandCardCount>2 && cbHandCardData[0]==0x4F && cbHandCardData[1]==0x4E && CT_ERROR!=GetCardType(cbHandCardData+2, cbHandCardCount-2) &&
				GetCardType(cbHandCardData+2, cbHandCardCount-2) !=CT_FOUR_LINE_TAKE_ONE &&
				GetCardType(cbHandCardData+2, cbHandCardCount-2) !=CT_FOUR_LINE_TAKE_TWO)
        {
            OutCardResult.cbCardCount = 2 ;
            OutCardResult.cbResultCard[0] = 0x4F ;
            OutCardResult.cbResultCard[1] = 0x4E ;
        }
        
        if(OutCardResult.cbCardCount>0)
        {
            return ;
        }
    }
    
    if(cbHandCardCount==3 && GetCardColor(cbHandCardData[0])==0x40 && GetCardColor(cbHandCardData[1])==0x40)
    {
        OutCardResult.cbCardCount = 2 ;
        OutCardResult.cbResultCard[0] = 0x4F ;
        OutCardResult.cbResultCard[1] = 0x4E ;
        return ;
    }
    else if(cbHandCardCount==2 && GetCardColor(cbHandCardData[0])==0x40 && GetCardColor(cbHandCardData[1])==0x40)
    {
        OutCardResult.cbCardCount = 2 ;
        OutCardResult.cbResultCard[0] = 0x4F ;
        OutCardResult.cbResultCard[1] = 0x4E ;
        return ;
    }
    else if(CT_ERROR!=GetCardType(cbHandCardData, cbHandCardCount) && CT_FOUR_LINE_TAKE_ONE!=GetCardType(cbHandCardData, cbHandCardCount)
			&& CT_FOUR_LINE_TAKE_TWO!=GetCardType(cbHandCardData, cbHandCardCount))
    {
        OutCardResult.cbCardCount = cbHandCardCount ;
        CopyMemory(OutCardResult.cbResultCard, cbHandCardData, cbHandCardCount) ;
        return ;
    }
    
    if(cbHandCardCount>=2)
    {
        tagOutCardTypeResult UpsideCanOutCardType1[13] ;
        ZeroMemory(UpsideCanOutCardType1, sizeof(UpsideCanOutCardType1)) ;
        tagOutCardTypeResult UpsideCanOutCardType2[13] ;
        ZeroMemory(UpsideCanOutCardType2, sizeof(UpsideCanOutCardType2)) ;
        
        tagOutCardTypeResult UndersideCanOutCardType1[13] ;
        ZeroMemory(UndersideCanOutCardType1, sizeof(UndersideCanOutCardType1)) ;
        tagOutCardTypeResult UndersideCanOutCardType2[13] ;
        ZeroMemory(UndersideCanOutCardType2, sizeof(UndersideCanOutCardType2)) ;
        
        BYTE cbFirstHandCardType = GetCardType(cbHandCardData, cbHandCardCount-1) ;
        BYTE cbSecondHandCardType = GetCardType(cbHandCardData+1, cbHandCardCount-1) ;
        
        BYTE cbAllBombCardData[MAX_COUNT], cbAllBombCount=0 ;
        GetAllBomCard(cbHandCardData, cbHandCardCount, cbAllBombCardData, cbAllBombCount) ;
        
        if (cbAllBombCount <= 0 && cbFirstHandCardType!=CT_THREE_LINE_TAKE_ONE && cbFirstHandCardType!=CT_THREE_LINE_TAKE_TWO)
        {
            if(CT_ERROR!=cbFirstHandCardType && cbFirstHandCardType!=CT_FOUR_LINE_TAKE_ONE && cbFirstHandCardType!= CT_FOUR_LINE_TAKE_TWO)
            {
                AnalyseOutCardType(m_cbAllCardData[wUpsideOfBanker], m_cbUserCardCount[wUpsideOfBanker], cbHandCardData, cbHandCardCount-1, UpsideCanOutCardType1) ;
                AnalyseOutCardType(m_cbAllCardData[wUndersideOfBanker], m_cbUserCardCount[wUndersideOfBanker], cbHandCardData, cbHandCardCount-1, UndersideCanOutCardType1) ;
            }
            if(CT_ERROR!=cbSecondHandCardType && cbSecondHandCardType!=CT_FOUR_LINE_TAKE_ONE && cbSecondHandCardType!= CT_FOUR_LINE_TAKE_TWO)
            {
                AnalyseOutCardType(m_cbAllCardData[wUpsideOfBanker], m_cbUserCardCount[wUpsideOfBanker], cbHandCardData+1, cbHandCardCount-1, UpsideCanOutCardType2) ;
                AnalyseOutCardType(m_cbAllCardData[wUndersideOfBanker], m_cbUserCardCount[wUndersideOfBanker], cbHandCardData+1, cbHandCardCount-1, UndersideCanOutCardType2) ;
            }
            
            if(cbSecondHandCardType!=CT_ERROR && cbSecondHandCardType!=CT_FOUR_LINE_TAKE_ONE && cbSecondHandCardType!= CT_FOUR_LINE_TAKE_TWO && UpsideCanOutCardType2[cbSecondHandCardType].cbCardTypeCount==0 && UndersideCanOutCardType2[cbSecondHandCardType].cbCardTypeCount==0 &&
               UpsideCanOutCardType2[CT_BOMB_CARD].cbCardTypeCount==0 && UndersideCanOutCardType2[CT_BOMB_CARD].cbCardTypeCount==0)
            {
                OutCardResult.cbCardCount = cbHandCardCount-1 ;
                CopyMemory(OutCardResult.cbResultCard, cbHandCardData+1, cbHandCardCount-1) ;
                return ;
            }
            
            if(cbFirstHandCardType!=CT_ERROR && cbFirstHandCardType!=CT_FOUR_LINE_TAKE_ONE && cbFirstHandCardType!= CT_FOUR_LINE_TAKE_TWO && UpsideCanOutCardType1[cbFirstHandCardType].cbCardTypeCount==0 && UndersideCanOutCardType1[cbFirstHandCardType].cbCardTypeCount==0 &&
               UpsideCanOutCardType2[CT_BOMB_CARD].cbCardTypeCount==0 && UndersideCanOutCardType2[CT_BOMB_CARD].cbCardTypeCount==0)
            {
                OutCardResult.cbCardCount = cbHandCardCount-1 ;
                CopyMemory(OutCardResult.cbResultCard, cbHandCardData, cbHandCardCount-1) ;
                return ;
            }
            
            if(GetCardLogicValue(cbHandCardData[0])>=GetCardLogicValue(m_cbAllCardData[wUpsideOfBanker][0]) &&
               GetCardLogicValue(cbHandCardData[0])>=GetCardLogicValue(m_cbAllCardData[wUndersideOfBanker][0]) &&
               CT_ERROR!=cbSecondHandCardType && cbSecondHandCardType!=CT_FOUR_LINE_TAKE_ONE && cbSecondHandCardType!= CT_FOUR_LINE_TAKE_TWO &&
               UpsideCanOutCardType2[CT_BOMB_CARD].cbCardTypeCount==0 && UndersideCanOutCardType2[CT_BOMB_CARD].cbCardTypeCount==0)
            {
                OutCardResult.cbCardCount = 1 ;
                OutCardResult.cbResultCard[0] = cbHandCardData[0] ;
                return ;
            }
            
            if(CT_ERROR!=cbSecondHandCardType && cbSecondHandCardType!=CT_FOUR_LINE_TAKE_ONE && cbSecondHandCardType!= CT_FOUR_LINE_TAKE_TWO &&
               UpsideCanOutCardType2[CT_BOMB_CARD].cbCardTypeCount==0 && UndersideCanOutCardType2[CT_BOMB_CARD].cbCardTypeCount==0)
            {
                OutCardResult.cbCardCount = cbHandCardCount-1 ;
                CopyMemory(OutCardResult.cbResultCard, cbHandCardData+1, cbHandCardCount-1) ;
                return ;
            }
        }
        else
        {
            BYTE cbRemainCard[MAX_COUNT], cbRemainCount=0 ;
            CopyMemory(cbRemainCard, cbHandCardData, cbHandCardCount) ;
            cbRemainCount = cbHandCardCount ;
            RemoveCard(cbAllBombCardData, cbAllBombCount, cbRemainCard, cbRemainCount) ;
            cbRemainCount -= cbAllBombCount ;
            if (GetCardType(cbRemainCard, cbRemainCount) != CT_ERROR)
            {
                OutCardResult.cbCardCount = cbRemainCount ;
                CopyMemory(OutCardResult.cbResultCard, cbRemainCard, cbRemainCount) ;
                return ;
            }
        }
    }
    
    {
        {
            tagOutCardTypeResult MeOutCardTypeResult[13] ;
            ZeroMemory(MeOutCardTypeResult, sizeof(MeOutCardTypeResult)) ;
            AnalyseOutCardType(cbHandCardData, cbHandCardCount, MeOutCardTypeResult) ;
            
            BYTE cbMinSingleCardCount[4] ;
            cbMinSingleCardCount[0]=MAX_COUNT ;
            cbMinSingleCardCount[1]=MAX_COUNT ;
            cbMinSingleCardCount[2]=MAX_COUNT ;
            cbMinSingleCardCount[3]=MAX_COUNT ;
            BYTE cbIndex[4]={0} ;
            BYTE cbOutcardType[4]={CT_ERROR} ;
            BYTE cbMinValue=MAX_COUNT ;
            BYTE cbMinSingleCountInFour=MAX_COUNT ;
            BYTE cbMinCardType=CT_ERROR ;
            BYTE cbMinIndex=0 ;
            
            for(BYTE cbCardType=CT_DOUBLE; cbCardType<CT_BOMB_CARD; ++cbCardType)
            {
                
                tagOutCardTypeResult const &tmpCardResult = MeOutCardTypeResult[cbCardType] ;
                
                BYTE cbThisHandCardCount = MAX_COUNT ;
                
                tagOutCardTypeResult UpsideOutCardTypeResult[13] ;
                ZeroMemory(UpsideOutCardTypeResult, sizeof(UpsideOutCardTypeResult)) ;
                
                tagOutCardTypeResult UndersideOutCardTypeResult[13] ;
                ZeroMemory(UndersideOutCardTypeResult, sizeof(UndersideOutCardTypeResult)) ;
                
                
                for(BYTE i=0; i<tmpCardResult.cbCardTypeCount; ++i)
                {
                    if ( cbCardType == CT_DOUBLE )
                    {
                        tagAnalyseResultA AnalyseResult ;
                        ZeroMemory( &AnalyseResult,  sizeof( AnalyseResult ) ) ;
                        AnalysebCardDataA( cbHandCardData, cbHandCardCount, AnalyseResult ) ;
                        if ( AnalyseResult.bSignedCount + AnalyseResult.bThreeCount * 3 == cbHandCardCount )
                        {
                            bool bContinue = false ;
                            for ( BYTE cbThreeIndex = 0; cbThreeIndex < AnalyseResult.bThreeCount; ++cbThreeIndex )
                                if ( GetCardValue(  tmpCardResult.cbCardData[i][0] ) == GetCardValue( AnalyseResult.m_bTCardData[3 * cbThreeIndex] ) )
                                {
                                    bContinue = true ;
                                    break ;
                                }
                            if ( bContinue ) continue ;
                        }
                    }
                    
                    BYTE cbTmpCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, tmpCardResult.cbCardData[i], tmpCardResult.cbEachHandCardCount[i]) ;
                    
                    if(tmpCardResult.cbEachHandCardCount[i]!=cbThisHandCardCount)
                    {
                        cbThisHandCardCount = tmpCardResult.cbEachHandCardCount[i] ;
                        AnalyseOutCardType(m_cbAllCardData[wUpsideOfBanker], m_cbUserCardCount[wUpsideOfBanker],
                                           tmpCardResult.cbCardData[i], tmpCardResult.cbEachHandCardCount[i] ,UpsideOutCardTypeResult) ;
                        AnalyseOutCardType(m_cbAllCardData[wUndersideOfBanker], m_cbUserCardCount[wUndersideOfBanker],
                                           tmpCardResult.cbCardData[i], tmpCardResult.cbEachHandCardCount[i] ,UndersideOutCardTypeResult) ;
                    }
                    BYTE cbMaxValue=0 ;
                    BYTE Index = 0 ;
                    
                    BYTE cbCurrentCardType = GetCardType(tmpCardResult.cbCardData[i], cbThisHandCardCount) ;
                    if (cbThisHandCardCount != cbHandCardCount && cbCurrentCardType >= CT_SINGLE_LINE && cbCurrentCardType <= CT_THREE_LINE_TAKE_TWO &&
                        ( GetCardLogicValue(tmpCardResult.cbCardData[i][cbThisHandCardCount-1]) > GetCardLogicValue(cbHandCardData[cbHandCardCount-2]) ||
                         GetCardLogicValue(tmpCardResult.cbCardData[i][0]) >= 11 ) )
                    {
                        BYTE cbRemainCardData[MAX_COUNT], cbRemainCardCount ;
                        CopyMemory(cbRemainCardData, cbHandCardData, cbHandCardCount) ;
                        cbRemainCardCount = cbHandCardCount ;
                        
                        RemoveCard(tmpCardResult.cbCardData[i], cbThisHandCardCount, cbRemainCardData, cbRemainCardCount) ;
                        cbRemainCardCount -= cbThisHandCardCount ;
                        
                        BYTE cbCurrentLargestLogicCard = GetCardLogicValue(tmpCardResult.cbCardData[i][0]) ;
                        
                        if (GetCardType(cbRemainCardData, cbRemainCardCount) == CT_ERROR && (cbCurrentCardType >= CT_THREE_LINE_TAKE_ONE &&
                                                                                             cbCurrentCardType <= CT_THREE_LINE_TAKE_TWO && cbCurrentLargestLogicCard >= 11 && cbThisHandCardCount <=5 ||
                                                                                             cbCurrentCardType == CT_SINGLE_LINE && cbThisHandCardCount <= 6 && cbCurrentLargestLogicCard >= 12 ||
                                                                                             cbCurrentCardType >= CT_DOUBLE_LINE && cbCurrentCardType <= CT_THREE_LINE && cbCurrentLargestLogicCard >= 12 && cbThisHandCardCount <= 8))
                        {
                            if ( cbCurrentCardType >= CT_SINGLE_LINE && cbCurrentCardType <= CT_THREE_LINE &&
                                GetCardLogicValue(tmpCardResult.cbCardData[i][cbThisHandCardCount - 1]) > GetCardLogicValue(cbHandCardData[cbHandCardCount-3]) )
                                continue ;
                            
                            if ( cbCurrentCardType >= CT_THREE_LINE_TAKE_ONE && cbCurrentCardType <= CT_THREE_LINE_TAKE_TWO &&
                                GetCardLogicValue(tmpCardResult.cbCardData[i][0]) > GetCardLogicValue(cbHandCardData[cbHandCardCount-3]) )
                                continue ;
                        }
                    }
                    
                    if (cbCardType == CT_DOUBLE && GetCardLogicValue(tmpCardResult.cbCardData[i][0]) >= 11)
                    {
                        BYTE cbAllSingleCardData[MAX_COUNT], cbAllSingleCount ;
                        cbAllSingleCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, NULL, 0, cbAllSingleCardData) ;
                        if (cbAllSingleCount >= 2 && GetCardLogicValue(cbAllSingleCardData[cbAllSingleCount-2]) < 10) continue ;
                    }
                    
                    if(UpsideOutCardTypeResult[cbCardType].cbCardTypeCount>0 || UndersideOutCardTypeResult[cbCardType].cbCardTypeCount>0)
                    {
                        if(UpsideOutCardTypeResult[cbCardType].cbEachHandCardCount[0] > 0 && m_cbUserCardCount[wUpsideOfBanker]<=UpsideOutCardTypeResult[cbCardType].cbEachHandCardCount[0]+1)
                            continue ;
                        
                        if(UndersideOutCardTypeResult[cbCardType].cbEachHandCardCount[0] > 0 && m_cbUserCardCount[wUndersideOfBanker]<=UndersideOutCardTypeResult[cbCardType].cbEachHandCardCount[0]+1)
                            continue ;
                        
                        //if(UpsideOutCardTypeResult[cbCardType].cbCardTypeCount > 0 && GetCardLogicValue(tmpCardResult.cbCardData[0][0]) < GetCardLogicValue(UpsideOutCardTypeResult[cbCardType].cbCardData[0][0]) ||
                        //	UpsideOutCardTypeResult[cbCardType].cbCardTypeCount > 0 && GetCardLogicValue(tmpCardResult.cbCardData[0][0]) < GetCardLogicValue(UpsideOutCardTypeResult[cbCardType].cbCardData[0][0]))
                        //	continue ;
                    }
                    if(tmpCardResult.cbEachHandCardCount[i] != cbHandCardCount)
                    {
                        bool bHaveLargeCard=false ;
                        for(BYTE j=0; j<tmpCardResult.cbEachHandCardCount[i]; ++j)
                        {
                            if(GetCardLogicValue(tmpCardResult.cbCardData[i][j])>=15) bHaveLargeCard=true ;
                            if(cbCardType!=CT_SINGLE_LINE && cbCardType!=CT_DOUBLE_LINE  && GetCardLogicValue(tmpCardResult.cbCardData[i][0])==14) bHaveLargeCard=true ;
                        }
                        
                        if(bHaveLargeCard)
                            continue ;
                    }
                    
                    for(BYTE j=0; j<4; ++j)
                    {
                        if(cbMinSingleCardCount[j]>=cbTmpCount)
                        {
                            cbMinSingleCardCount[j] = cbTmpCount ;
                            cbIndex[j] = i ;
                            cbOutcardType[j] = cbCardType ;
                            break ;
                        }
                    }
                    
                    if(cbMinSingleCountInFour>=cbTmpCount)
                    {
                        cbMinCardType = cbCardType ;
                        cbMinSingleCountInFour=cbTmpCount ;
                        cbMinIndex=i ;
                    }
                }
            }
            
            if(cbMinSingleCountInFour>=AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, NULL, 0)+3 &&
               (m_cbUserCardCount[wUndersideOfBanker]>=4 && m_cbUserCardCount[wUpsideOfBanker]>=4))
                cbMinSingleCountInFour=MAX_COUNT ;
            
            if(cbMinSingleCountInFour!=MAX_COUNT)
            {
                BYTE Index = cbMinIndex ;
                
                for(BYTE i=0; i<4; ++i)
                {
                    if(cbOutcardType[i]==cbMinCardType && cbMinSingleCardCount[i]<=cbMinSingleCountInFour &&
                       GetCardLogicValue(MeOutCardTypeResult[cbMinCardType].cbCardData[cbIndex[i]][0])<GetCardLogicValue(MeOutCardTypeResult[cbMinCardType].cbCardData[Index][0]))
                        Index = cbIndex[i] ;
                }
                
                if(cbHandCardCount==3 && GetCardColor(cbHandCardData[0])==0x40 && GetCardColor(cbHandCardData[1])==0x40)
                {
                    OutCardResult.cbCardCount = 2 ;
                    OutCardResult.cbResultCard[0] = 0x4F ;
                    OutCardResult.cbResultCard[1] = 0x4E ;
                    return ;
                }
                else if(cbHandCardCount==2 && GetCardColor(cbHandCardData[0])==0x40 && GetCardColor(cbHandCardData[1])==0x40)
                {
                    OutCardResult.cbCardCount = 2 ;
                    OutCardResult.cbResultCard[0] = 0x4F ;
                    OutCardResult.cbResultCard[1] = 0x4E ;
                    return ;
                }
                else
                {
                    OutCardResult.cbCardCount=MeOutCardTypeResult[cbMinCardType].cbEachHandCardCount[Index];
                    CopyMemory(OutCardResult.cbResultCard,MeOutCardTypeResult[cbMinCardType].cbCardData[Index],MeOutCardTypeResult[cbMinCardType].cbEachHandCardCount[Index]*sizeof(BYTE));
                    return ;
                }
                
                return ;
            }
            
            if(OutCardResult.cbCardCount<=0 && (m_cbUserCardCount[wUndersideOfBanker] == 1 || m_cbUserCardCount[wUpsideOfBanker] == 1))
            {
                if(MeOutCardTypeResult[CT_SINGLE].cbCardTypeCount>0)
                {
                    BYTE Index=MAX_COUNT ;
                    for(BYTE i=0; i<MeOutCardTypeResult[CT_SINGLE].cbCardTypeCount; ++i)
                    {
                        if((m_cbUserCardCount[wUndersideOfBanker] == 1 && GetCardLogicValue(MeOutCardTypeResult[CT_SINGLE].cbCardData[i][0])>=GetCardLogicValue(m_cbAllCardData[wUndersideOfBanker][0])) ||
                           (m_cbUserCardCount[wUpsideOfBanker] == 1 && GetCardLogicValue(MeOutCardTypeResult[CT_SINGLE].cbCardData[i][0])>=GetCardLogicValue(m_cbAllCardData[wUpsideOfBanker][0])))
                        {
                            Index=i ;
                        }
                        else break ;
                    }
                    
                    if(MAX_COUNT!=Index)
                    {
                        OutCardResult.cbCardCount = MeOutCardTypeResult[CT_SINGLE].cbEachHandCardCount[Index] ;
                        CopyMemory(OutCardResult.cbResultCard, MeOutCardTypeResult[CT_SINGLE].cbCardData[Index], OutCardResult.cbCardCount) ;
                        return ;
                    }
                }
            }
        }
    }
    BYTE cbFirstCard=0 ;
    for(BYTE i=0; i<cbHandCardCount; ++i)
        if(GetCardLogicValue(cbHandCardData[i])<15)
        {
            cbFirstCard = i ;
            break ;
        }
    
    if(cbFirstCard<cbHandCardCount-1)
        AnalyseOutCardType(cbHandCardData+cbFirstCard, cbHandCardCount-cbFirstCard, CardTypeResult) ;
    else
        AnalyseOutCardType(cbHandCardData, cbHandCardCount, CardTypeResult) ;
    
    BYTE cbMinSingleCardCount[4] ;
    cbMinSingleCardCount[0]=MAX_COUNT ;
    cbMinSingleCardCount[1]=MAX_COUNT ;
    cbMinSingleCardCount[2]=MAX_COUNT ;
    cbMinSingleCardCount[3]=MAX_COUNT ;
    BYTE cbIndex[4]={0} ;
    BYTE cbOutcardType[4]={CT_ERROR} ;
    BYTE cbMinValue=MAX_COUNT ;
    BYTE cbMinSingleCountInFour=MAX_COUNT ;
    BYTE cbMinCardType=CT_ERROR ;
    BYTE cbMinIndex=0 ;
    
    for(BYTE cbCardType=CT_SINGLE; cbCardType<CT_BOMB_CARD; ++cbCardType)
    {
        tagOutCardTypeResult const &tmpCardResult = CardTypeResult[cbCardType] ;
        for(BYTE i=0; i<tmpCardResult.cbCardTypeCount; ++i)
        {
            if ( CompareCard(tmpCardResult.cbCardData[i], m_cbAllCardData[wUndersideOfBanker], tmpCardResult.cbEachHandCardCount[i], m_cbUserCardCount[wUndersideOfBanker]) ||
                CompareCard(tmpCardResult.cbCardData[i],  m_cbAllCardData[wUpsideOfBanker], tmpCardResult.cbEachHandCardCount[i],m_cbUserCardCount[wUpsideOfBanker]))
                continue ;
            
            if ( tmpCardResult.cbEachHandCardCount[i] != cbHandCardCount && cbCardType >= CT_SINGLE_LINE && cbCardType <= CT_THREE_LINE_TAKE_TWO &&
                ( GetCardLogicValue(tmpCardResult.cbCardData[i][tmpCardResult.cbEachHandCardCount[i]-1]) > GetCardLogicValue(cbHandCardData[cbHandCardCount-2]) ||
                 GetCardLogicValue(tmpCardResult.cbCardData[i][0]) >= 11 ))
            {
                BYTE cbRemainCardData[MAX_COUNT], cbRemainCardCount ;
                CopyMemory(cbRemainCardData, cbHandCardData, cbHandCardCount) ;
                cbRemainCardCount = cbHandCardCount ;
                
                RemoveCard(tmpCardResult.cbCardData[i], tmpCardResult.cbEachHandCardCount[i], cbRemainCardData, cbRemainCardCount) ;
                cbRemainCardCount -= tmpCardResult.cbEachHandCardCount[i] ;
                
                BYTE cbCurrentLargestLogicCard = GetCardLogicValue(tmpCardResult.cbCardData[i][0]) ;
                
                if (GetCardType(cbRemainCardData, cbRemainCardCount) == CT_ERROR && (cbCardType >= CT_THREE_LINE_TAKE_ONE &&
                                                                                     cbCardType <= CT_THREE_LINE_TAKE_TWO && cbCurrentLargestLogicCard >= 11 && tmpCardResult.cbEachHandCardCount[i] <=5 ||
                                                                                     cbCardType == CT_SINGLE_LINE && tmpCardResult.cbEachHandCardCount[i] <= 6 && cbCurrentLargestLogicCard >= 12 ||
                                                                                     cbCardType >= CT_DOUBLE_LINE && cbCardType <= CT_THREE_LINE && cbCurrentLargestLogicCard >= 12 && tmpCardResult.cbEachHandCardCount[i] <= 8))
                {
                    if ( cbCardType >= CT_SINGLE_LINE && cbCardType <= CT_THREE_LINE &&
                        GetCardLogicValue(tmpCardResult.cbCardData[i][tmpCardResult.cbEachHandCardCount[i] - 1]) > GetCardLogicValue(cbHandCardData[cbHandCardCount-3]) )
                        continue ;
                    
                    if ( cbCardType >= CT_THREE_LINE_TAKE_ONE && cbCardType <= CT_THREE_LINE_TAKE_TWO &&
                        GetCardLogicValue(tmpCardResult.cbCardData[i][0]) > GetCardLogicValue(cbHandCardData[cbHandCardCount-3]) )
                        continue ;
                }
            }
            
            BYTE cbTmpCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, tmpCardResult.cbCardData[i], tmpCardResult.cbEachHandCardCount[i]) ;
            
            BYTE cbMaxValue=0 ;
            BYTE Index = 0 ;
            
            for(BYTE j=0; j<4; ++j)
            {
                if(cbMinSingleCardCount[j]>=cbTmpCount)
                {
                    cbMinSingleCardCount[j] = cbTmpCount ;
                    cbIndex[j] = i ;
                    cbOutcardType[j] = cbCardType ;
                    break ;
                }
            }
            
            if(cbMinSingleCountInFour>=cbTmpCount)
            {
                cbMinCardType = cbCardType ;
                cbMinSingleCountInFour=cbTmpCount ;
                cbMinIndex=i ;
            }
        }
    }
    
    if(cbMinSingleCountInFour!=MAX_COUNT)
    {
        BYTE Index = cbMinIndex ;
        
        for(BYTE i=0; i<4; ++i)
        {
            if(cbOutcardType[i]==cbMinCardType && cbMinSingleCardCount[i]<=cbMinSingleCountInFour &&
               GetCardLogicValue(CardTypeResult[cbMinCardType].cbCardData[cbIndex[i]][0])<GetCardLogicValue(CardTypeResult[cbMinCardType].cbCardData[Index][0]))
                Index = cbIndex[i] ;
        }
        
        if(cbHandCardCount==3 && GetCardColor(cbHandCardData[0])==0x40 && GetCardColor(cbHandCardData[1])==0x40)
        {
            OutCardResult.cbCardCount = 2 ;
            OutCardResult.cbResultCard[0] = 0x4F ;
            OutCardResult.cbResultCard[1] = 0x4E ;
            return ;
        }
        else if(cbHandCardCount==2 && GetCardColor(cbHandCardData[0])==0x40 && GetCardColor(cbHandCardData[1])==0x40)
        {
            OutCardResult.cbCardCount = 2 ;
            OutCardResult.cbResultCard[0] = 0x4F ;
            OutCardResult.cbResultCard[1] = 0x4E ;
            return ;
        }
        else
        {
            OutCardResult.cbCardCount=CardTypeResult[cbMinCardType].cbEachHandCardCount[Index];
            CopyMemory(OutCardResult.cbResultCard,CardTypeResult[cbMinCardType].cbCardData[Index],CardTypeResult[cbMinCardType].cbEachHandCardCount[Index]*sizeof(BYTE));
            return ;
        }
        return ;
    }
    else if (CardTypeResult[CT_BOMB_CARD].cbCardTypeCount > 0)
    {
        
    }
    
    BYTE cbAllSingleCardData[MAX_COUNT], cbAllSingleCardCount ;
    cbAllSingleCardCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, NULL, 0, cbAllSingleCardData) ;
    
    if ( cbAllSingleCardCount > 0 )
    {
        if ( ( 1 == m_cbUserCardCount[wUndersideOfBanker] || 1 == m_cbUserCardCount[wUpsideOfBanker] ) && cbAllSingleCardCount >= 2 )
        {
            OutCardResult.cbCardCount = 1 ;
            OutCardResult.cbResultCard[0] = cbAllSingleCardData[cbAllSingleCardCount-2] ;
        }
        else
        {
            OutCardResult.cbCardCount = 1 ;
            OutCardResult.cbResultCard[0] = cbAllSingleCardData[cbAllSingleCardCount-1] ;
        }
        return ;
    }
    
    OutCardResult.cbCardCount = 1 ;
    OutCardResult.cbResultCard[0] = cbHandCardData[cbHandCardCount-1] ;
    
    return ;
}

void DDZCGameLogicSingle::BankerOutCard(const BYTE cbHandCardData[], BYTE cbHandCardCount, WORD wOutCardUser, const BYTE cbTurnCardData[], BYTE cbTurnCardCount, tagOutCardResult & OutCardResult)
{
	ZeroMemory(&OutCardResult, sizeof(OutCardResult)) ;
    
	tagOutCardTypeResult CardTypeResult[12+1] ;
	ZeroMemory(CardTypeResult, sizeof(CardTypeResult)) ;
    
	BYTE cbOutCardType = GetCardType(cbTurnCardData,cbTurnCardCount) ;
	AnalyseOutCardType(cbHandCardData,cbHandCardCount,cbTurnCardData,cbTurnCardCount, CardTypeResult) ;
    
	WORD wUndersideUser = (m_wBankerUser+1)%GAME_PLAYER ;
	WORD wUpsideUser = (wUndersideUser+1)%GAME_PLAYER ;
    
	if(cbHandCardCount==CardTypeResult[CT_BOMB_CARD].cbEachHandCardCount[0] && (cbOutCardType<CT_BOMB_CARD ||
                                                                                GetCardLogicValue(CardTypeResult[CT_BOMB_CARD].cbCardData[0][0])>GetCardLogicValue(cbTurnCardData[0])))
	{
		OutCardResult.cbCardCount = CardTypeResult[CT_BOMB_CARD].cbEachHandCardCount[0] ;
		CopyMemory(OutCardResult.cbResultCard,  CardTypeResult[CT_BOMB_CARD].cbCardData, OutCardResult.cbCardCount) ;
        
		return ;
	}
	else if(cbHandCardCount>2 && cbHandCardData[0]==0x4F && cbHandCardData[1]==0x4E && CT_ERROR!=GetCardType(cbHandCardData+2, cbHandCardCount-2) &&
            CT_FOUR_LINE_TAKE_ONE != GetCardType(cbHandCardData+2, cbHandCardCount-2) && CT_FOUR_LINE_TAKE_TWO != GetCardType(cbHandCardData+2, cbHandCardCount-2))
	{
		OutCardResult.cbCardCount = 2 ;
		OutCardResult.cbResultCard[0] = 0x4F ;
		OutCardResult.cbResultCard[1] = 0x4E ;
		return  ;
	}
    
	BYTE cbRemainCard[MAX_COUNT], cbRemainCount=0;
	BYTE cbAllBombCard[MAX_COUNT], cbAllBombCount=0 ;
	GetAllBomCard(cbHandCardData, cbHandCardCount, cbAllBombCard, cbAllBombCount) ;
    
	if(cbAllBombCount>0)
	{
		CopyMemory(cbRemainCard, cbHandCardData, cbHandCardCount) ;
		cbRemainCount = cbHandCardCount ;
		RemoveCard(cbAllBombCard, cbAllBombCount, cbRemainCard, cbRemainCount) ;
		cbRemainCount -= cbAllBombCount ;
        
		if(CT_ERROR != GetCardType(cbRemainCard, cbRemainCount) ||
           (2==cbRemainCount && GetCardLogicValue(cbRemainCard[0])>GetCardLogicValue(m_cbAllCardData[wUndersideUser][0]) &&
			GetCardLogicValue(cbRemainCard[0])>GetCardLogicValue(m_cbAllCardData[wUpsideUser][0])))
		{
			if((cbOutCardType<CT_BOMB_CARD || GetCardLogicValue(cbAllBombCard[0])>GetCardLogicValue(cbTurnCardData[0])) &&
               ( CardTypeResult[cbOutCardType].cbCardTypeCount <= 0 || CT_ERROR != GetCardType(cbRemainCard, cbRemainCount) ) )
			{
				if(GetCardColor(cbAllBombCard[0])==0x40)
				{
					OutCardResult.cbCardCount = 2 ;
					OutCardResult.cbResultCard[0] = 0x4F ;
					OutCardResult.cbResultCard[1] = 0x4E ;
					return ;
				}
				else
				{
					BYTE cbUnderSideBankerAllBombCard[MAX_COUNT], cbUnderSideBankerAllBombCardCount ;
					GetAllBomCard( m_cbAllCardData[wUndersideUser], m_cbUserCardCount[wUndersideUser], cbUnderSideBankerAllBombCard, cbUnderSideBankerAllBombCardCount) ;
                    
					BYTE cbUpSideBankerAllBombCard[MAX_COUNT], cbUpSideBankerAllBombCardCount ;
					GetAllBomCard( m_cbAllCardData[wUpsideUser], m_cbUserCardCount[wUpsideUser], cbUpSideBankerAllBombCard, cbUpSideBankerAllBombCardCount) ;
                    
					if ( !CompareCard( cbTurnCardData, cbRemainCard, cbTurnCardCount, cbRemainCount) ||  ( cbUnderSideBankerAllBombCardCount <= 0 && cbUpSideBankerAllBombCardCount )||
						( GetCardLogicValue( cbAllBombCard[0] ) > GetCardLogicValue( cbUnderSideBankerAllBombCard[0] ) &&
                         GetCardLogicValue( cbAllBombCard[0] ) > GetCardLogicValue( cbUpSideBankerAllBombCard[0] )) )
					{
						OutCardResult.cbCardCount = 4 ;
						CopyMemory(OutCardResult.cbResultCard, cbAllBombCard, 4) ;
						return ;
					}
				}
			}
		}
	}
    
	BYTE cbSingleCardCount = MAX_COUNT+CT_MISSILE_CARD ;
	bool bFindBestCard = false ;
	for(BYTE cbCardType=CT_SINGLE; cbCardType<=CT_MISSILE_CARD; ++cbCardType)
		if(CardTypeResult[cbCardType].cbCardTypeCount>0)
		{
			for(long lIndex=0; lIndex<CardTypeResult[cbCardType].cbCardTypeCount; ++lIndex)
			{
				if(TestOutAllCard(m_wBankerUser, CardTypeResult[cbCardType].cbCardData[lIndex], CardTypeResult[cbCardType].cbEachHandCardCount[lIndex], false))
				{
					BYTE cbTmpSingleCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, CardTypeResult[cbCardType].cbCardData[lIndex],
                                                                  CardTypeResult[cbCardType].cbEachHandCardCount[lIndex]) ;
                    
					if (cbTmpSingleCount >= MAX_COUNT) continue ;
                    
					BYTE cbBombCardType = GetCardType(CardTypeResult[cbCardType].cbCardData[lIndex], CardTypeResult[cbCardType].cbEachHandCardCount[lIndex]) ;
					if (cbBombCardType == CT_BOMB_CARD) cbTmpSingleCount += 4 ;
					else if (cbBombCardType == CT_MISSILE_CARD) cbTmpSingleCount += 5 ;
                    
                    
                    
					if (cbTmpSingleCount <= cbSingleCardCount)
					{
						OutCardResult.cbCardCount=CardTypeResult[cbCardType].cbEachHandCardCount[lIndex];
						CopyMemory(OutCardResult.cbResultCard, CardTypeResult[cbCardType].cbCardData[lIndex],
                                   CardTypeResult[cbCardType].cbEachHandCardCount[lIndex]*sizeof(BYTE));
						cbSingleCardCount = cbTmpSingleCount ;
						bFindBestCard = true ;
					}
				}
			}
		}
    if (bFindBestCard) return ;
    
    BYTE cbMinSingleCardCount[4] ;
    cbMinSingleCardCount[0]=MAX_COUNT ;
    cbMinSingleCardCount[1]=MAX_COUNT ;
    cbMinSingleCardCount[2]=MAX_COUNT ;
    cbMinSingleCardCount[3]=MAX_COUNT ;
    BYTE cbIndex[4]={0} ;
    BYTE cbMinSingleCountInFour=MAX_COUNT ;
    
    tagOutCardTypeResult const &CanOutCard = CardTypeResult[cbOutCardType] ;
    
    for(BYTE i=0; i<CanOutCard.cbCardTypeCount; ++i)
    {
        BYTE cbTmpCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount,CanOutCard.cbCardData[i], CanOutCard.cbEachHandCardCount[i]) ;
        BYTE cbMaxValue=0 ;
        BYTE Index = 0 ;
        
        for(BYTE j=0; j<4; ++j)
        {
            if(cbMinSingleCardCount[j]>=cbTmpCount)
            {
                cbMinSingleCardCount[j] = cbTmpCount ;
                cbIndex[j] = i ;
                break ;
            }
        }
        
    }
    
    for(BYTE i=0; i<4; ++i)
        if(cbMinSingleCountInFour>cbMinSingleCardCount[i]) cbMinSingleCountInFour = cbMinSingleCardCount[i] ;
    
    
    BYTE cbOriginSingleCardCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount,NULL,0) ;
    
    if(CanOutCard.cbCardTypeCount>0 && cbMinSingleCountInFour < MAX_COUNT)
    {
        BYTE cbMinLogicCardValue = GetCardLogicValue(0x4F)+1 ;
        bool bFindCard = false ;
        BYTE cbCanOutIndex=0 ;
        for(BYTE i=0; i<4; ++i)
        {
            BYTE Index = cbIndex[i] ;
            
            if((cbMinSingleCardCount[i]<cbOriginSingleCardCount+3)  &&  (cbMinSingleCardCount[i]<=cbMinSingleCountInFour || cbMinSingleCardCount[i]<=cbMinSingleCountInFour+1 &&
                                                                         CanOutCard.cbCardType >= CT_THREE_LINE_TAKE_ONE && CanOutCard.cbCardType <= CT_THREE_LINE_TAKE_TWO ) &&
               cbMinLogicCardValue>GetCardLogicValue(CanOutCard.cbCardData[Index][0]))
            {
                
                bool bNoLargeCard = true ;
                
                if(m_cbUserCardCount[wOutCardUser]>=4 && cbHandCardCount>=5  && CanOutCard.cbEachHandCardCount[Index]>=2 &&
                   GetCardLogicValue(CanOutCard.cbCardData[Index][0])>=15 &&
                   GetCardLogicValue(cbTurnCardData[0])<13 &&
                   (wOutCardUser==wUndersideUser&&GetCardLogicValue(cbTurnCardData[0])<GetCardLogicValue(m_cbAllCardData[wUndersideUser][0]) || wOutCardUser==wUpsideUser&&GetCardLogicValue(cbTurnCardData[0])<GetCardLogicValue(m_cbAllCardData[wUpsideUser][0])) &&
                   CanOutCard.cbEachHandCardCount[Index]!=cbHandCardCount)
                    bNoLargeCard=false ;
                
                
                for(BYTE k=3; k<CanOutCard.cbEachHandCardCount[Index]; ++k)
                {
                    if(GetCardLogicValue(CanOutCard.cbCardData[Index][k])>=15 &&
                       CanOutCard.cbEachHandCardCount[Index]!=cbHandCardCount)
                        bNoLargeCard = false ;
                }
                if(bNoLargeCard)
                {
                    bFindCard = true ;
                    cbCanOutIndex = Index ;
                    cbMinLogicCardValue = GetCardLogicValue(CanOutCard.cbCardData[Index][0]) ;
                }
            }
        }
        
        if(bFindCard)
        {
            BYTE cbLargestLogicCard ;
            if(wOutCardUser==wUndersideUser) cbLargestLogicCard = GetCardLogicValue(m_cbAllCardData[wUndersideUser][0]) ;
            else if(wOutCardUser==wUpsideUser) cbLargestLogicCard = GetCardLogicValue(m_cbAllCardData[wUpsideUser][0]) ;
            bool bCanOut=true ;
            
            if(GetCardLogicValue(cbTurnCardData[0])<cbLargestLogicCard)
            {
                if(GetCardColor(CanOutCard.cbCardData[cbCanOutIndex][0])==0x40 && GetCardLogicValue(cbTurnCardData[0])<=14 && cbHandCardCount>5)
                {
                    bCanOut = false ;
                }
            }
            
            if(GetCardLogicValue(CanOutCard.cbCardData[cbCanOutIndex][0])>=16 && cbHandCardCount>=2 && cbHandCardData[0]==0x4F && cbHandCardData[1]==0x4E)
            {
                bool bOutMissileCard = false ;
                BYTE cbRemainCardData[20], cbRemainCardCount=cbHandCardCount ;
                CopyMemory(cbRemainCardData, cbHandCardData, cbHandCardCount) ;
                RemoveCard(cbRemainCardData, 2, cbRemainCardData, cbRemainCardCount) ;
                cbRemainCardCount -= 2 ;
                if(CT_ERROR!=GetCardType(cbRemainCardData, cbRemainCardCount)) bOutMissileCard = true;
                
                BYTE cbRemainLargestCard = GetCardLogicValue(cbRemainCardData[0]) ;
                if(cbRemainCardCount<5 && cbRemainCardCount>0 && GetCardLogicValue(cbRemainCardData[0])>=14) bOutMissileCard = true;
                
                BYTE cbSingleCardCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, CanOutCard.cbCardData[cbCanOutIndex],
                                                               CanOutCard.cbEachHandCardCount[cbCanOutIndex]) ;
                if(cbSingleCardCount<=1 && GetCardLogicValue(cbRemainCardData[0])>=11) bOutMissileCard = true;
                
                if (GetCardLogicValue(cbRemainCardData[0]) <= 10 && CT_ERROR == GetCardType(cbRemainCardData, cbRemainCardCount) &&
                    (GetCardLogicValue(m_cbAllCardData[(1+m_wBankerUser) % GAME_PLAYER][0]) > 10 || GetCardLogicValue(m_cbAllCardData[(2+m_wBankerUser) % GAME_PLAYER][0]) > 10))
                    bOutMissileCard = false ;
                
                if(bOutMissileCard)
                {
                    BYTE cbIndex = CardTypeResult[CT_BOMB_CARD].cbCardTypeCount - 1 ;
                    
                    OutCardResult.cbCardCount = CardTypeResult[CT_BOMB_CARD].cbEachHandCardCount[cbIndex] ;
                    CopyMemory(OutCardResult.cbResultCard, CardTypeResult[CT_BOMB_CARD].cbCardData[cbIndex], OutCardResult.cbCardCount) ;
                    return ;
                }
            }
            
            if(bCanOut)
            {
                OutCardResult.cbCardCount=CanOutCard.cbEachHandCardCount[cbCanOutIndex];
                CopyMemory(OutCardResult.cbResultCard,CanOutCard.cbCardData[cbCanOutIndex],CanOutCard.cbEachHandCardCount[cbCanOutIndex]*sizeof(BYTE));
                
                return ;
            }
        }
        
        if(cbOutCardType==CT_SINGLE)
        {
            BYTE cbLargestLogicCard ;
            if(wOutCardUser==wUndersideUser) cbLargestLogicCard = GetCardLogicValue(m_cbAllCardData[wUndersideUser][0]) ;
            else if(wOutCardUser==wUpsideUser) cbLargestLogicCard = GetCardLogicValue(m_cbAllCardData[wUpsideUser][0]) ;
            
            if(GetCardLogicValue(cbTurnCardData[0])==14 ||
               GetCardLogicValue(cbTurnCardData[0])>=cbLargestLogicCard ||
               (GetCardLogicValue(cbTurnCardData[0])<cbLargestLogicCard-1) ||
               (wOutCardUser==wUndersideUser&&m_cbUserCardCount[wUndersideUser]<=5 || wOutCardUser==wUpsideUser&&m_cbUserCardCount[wUpsideUser]<=5))
            {
                BYTE cbIndex=MAX_COUNT ;
                for(BYTE i=0; i<cbHandCardCount; ++i)
                    if(GetCardLogicValue(cbHandCardData[i])>GetCardLogicValue(cbTurnCardData[0]) &&
                       GetCardLogicValue(cbHandCardData[i])>=15)
                    {
                        cbIndex = i ;
                    }
                if(cbIndex!=MAX_COUNT)
                {
                    OutCardResult.cbCardCount=1;
                    OutCardResult.cbResultCard[0] = cbHandCardData[cbIndex] ;
                    
                    return ;
                }
            }
        }
        
        
        BYTE cbMinSingleCount=MAX_COUNT ;
        BYTE Index=0 ;
        for(BYTE i=0; i<CardTypeResult[cbOutCardType].cbCardTypeCount; ++i)
        {
            BYTE cbTmpCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, CardTypeResult[cbOutCardType].cbCardData[i], CardTypeResult[cbOutCardType].cbEachHandCardCount[i]) ;
            if(cbMinSingleCount>=cbTmpCount)
            {
                cbMinSingleCount = cbTmpCount ;
                Index = i ;
            }
        }
        OutCardResult.cbCardCount=CardTypeResult[cbOutCardType].cbEachHandCardCount[Index];
        CopyMemory(OutCardResult.cbResultCard, CardTypeResult[cbOutCardType].cbCardData[Index], OutCardResult.cbCardCount) ;
        
        return ;
    }
    
    if(CardTypeResult[CT_BOMB_CARD].cbCardTypeCount>0)
    {
        tagOutCardTypeResult const &BomCard = CardTypeResult[CT_BOMB_CARD] ;
        BYTE cbMinLogicValue = GetCardLogicValue(BomCard.cbCardData[0][0]) ;
        BYTE Index = 0 ;
        for(BYTE i=0; i<BomCard.cbCardTypeCount; ++i)
        {
            if(cbMinLogicValue>GetCardLogicValue(BomCard.cbCardData[i][0]))
            {
                cbMinLogicValue = GetCardLogicValue(BomCard.cbCardData[i][0]) ;
                Index = i ;
            }
        }
        
        bool bOutBomb=false ;
        
        BYTE cbRemainCardData[20], cbRemainCardCount=cbHandCardCount ;
        CopyMemory(cbRemainCardData, cbHandCardData, cbHandCardCount) ;
        RemoveCard(BomCard.cbCardData[Index], BomCard.cbEachHandCardCount[Index], cbRemainCardData, cbRemainCardCount) ;
        cbRemainCardCount -= BomCard.cbEachHandCardCount[Index] ;
        if(CT_ERROR!=GetCardType(cbRemainCardData, cbRemainCardCount)) bOutBomb = true ;
        
        BYTE cbSingleCardCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, BomCard.cbCardData[Index],BomCard.cbEachHandCardCount[Index]) ;
        if(cbSingleCardCount==0 && GetCardLogicValue(cbRemainCardData[0]) >
           GetCardLogicValue(m_cbAllCardData[wUpsideUser == wOutCardUser ? wUndersideUser : wUpsideUser][0])) bOutBomb = true ;
        
        BYTE cbRemainCardType = GetCardType(m_cbAllCardData[wOutCardUser], m_cbUserCardCount[wOutCardUser]) ;
        if(cbRemainCardType>CT_ERROR && cbRemainCardType<CT_FOUR_LINE_TAKE_ONE && GetCardLogicValue(m_cbAllCardData[wOutCardUser][0])<15 &&
           cbSingleCardCount < 2 && (GetCardLogicValue(cbRemainCardData[0]) >= GetCardLogicValue(m_cbAllCardData[wUndersideUser][0]) &&
                                     GetCardLogicValue(cbRemainCardData[0]) >= GetCardLogicValue(m_cbAllCardData[wUpsideUser][0]))) bOutBomb = true ;
        
        if (cbRemainCardType != CT_ERROR && m_lBankerOutCardCount == 1) bOutBomb = true ;
        
        BYTE cbRemainLargestCard = GetCardLogicValue(cbRemainCardData[0]) ;
        if(cbRemainCardCount<5 && cbRemainCardCount>0 && (cbRemainLargestCard!=GetCardLogicValue(BomCard.cbCardData[Index][0])) &&
           cbRemainLargestCard>GetCardLogicValue(m_cbAllCardData[wOutCardUser][0]) && cbRemainLargestCard > 14) bOutBomb = true ;
        
        tagAnalyseResultA AnalyseResult ;
        AnalysebCardDataA(cbRemainCardData, cbRemainCardCount, AnalyseResult) ;
        
        if (m_cbUserCardCount[wOutCardUser] == 1 && (AnalyseResult.bDoubleCount * 2 + AnalyseResult.bThreeCount * 3 + AnalyseResult.bFourCount * 4 + 1 >= cbRemainCardCount)) bOutBomb = true ;
        
        
        if(bOutBomb)
        {
            OutCardResult.cbCardCount=BomCard.cbEachHandCardCount[Index];
            CopyMemory(OutCardResult.cbResultCard,BomCard.cbCardData[Index],BomCard.cbEachHandCardCount[Index]*sizeof(BYTE));
        }
        return ;
    }
    
    return ;
}
void DDZCGameLogicSingle::UpsideOfBankerOutCard(const BYTE cbHandCardData[], BYTE cbHandCardCount, WORD wMeChairID, tagOutCardResult & OutCardResult)
{
	ZeroMemory(&OutCardResult, sizeof(OutCardResult)) ;
    
	printf("m_cbUserCardCount[m_wBankerUser]=%d \n",m_cbUserCardCount[m_wBankerUser]);
	
	if (m_cbUserCardCount[m_wBankerUser] == 1)
	{
		BYTE cbSingleCardData[MAX_COUNT] ;
		BYTE cbSingleCardCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, NULL, 0, cbSingleCardData) ;
        
		if (cbSingleCardCount == cbHandCardCount)
		{
			OutCardResult.cbCardCount = 1 ;
			OutCardResult.cbResultCard[0] = cbHandCardData[0] ;
            
			return ;
		}
	}
    
	tagOutCardTypeResult CardTypeResult[12+1] ;
	ZeroMemory(CardTypeResult, sizeof(CardTypeResult)) ;
    
	BYTE cbLineCard[MAX_COUNT] ;
	BYTE cbThreeLineCard[MAX_COUNT] ;
	BYTE cbDoubleLineCard[MAX_COUNT] ;
	BYTE cbLineCardCount;
	BYTE cbThreeLineCardCount ;
	BYTE cbDoubleLineCount ;
	GetAllLineCard(cbHandCardData, cbHandCardCount, cbLineCard, cbLineCardCount) ;
	GetAllThreeCard(cbHandCardData, cbHandCardCount, cbThreeLineCard, cbThreeLineCardCount) ;
	GetAllDoubleCard(cbHandCardData, cbHandCardCount, cbDoubleLineCard, cbDoubleLineCount) ;
    
	BYTE cbSingleCardCount = MAX_COUNT+CT_MISSILE_CARD ;
	bool bFindBestCard = false ;
	AnalyseOutCardType(cbHandCardData, cbHandCardCount, CardTypeResult) ;
	for(BYTE cbCardType=CT_SINGLE; cbCardType<=CT_MISSILE_CARD; ++cbCardType)
		if(CardTypeResult[cbCardType].cbCardTypeCount>0)
		{
			for(long lIndex=0; lIndex<CardTypeResult[cbCardType].cbCardTypeCount; ++lIndex)
			{
				WORD wMeChairID = (m_wBankerUser+2)%GAME_PLAYER ;
                
				if(TestOutAllCard(wMeChairID, CardTypeResult[cbCardType].cbCardData[lIndex], CardTypeResult[cbCardType].cbEachHandCardCount[lIndex], true))
				{
					BYTE cbTmpSingleCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, CardTypeResult[cbCardType].cbCardData[lIndex],
                                                                  CardTypeResult[cbCardType].cbEachHandCardCount[lIndex]) ;
                    
					if (cbTmpSingleCount >= MAX_COUNT) continue ;
                    
					BYTE cbBombCardType = GetCardType(CardTypeResult[cbCardType].cbCardData[lIndex], CardTypeResult[cbCardType].cbEachHandCardCount[lIndex]) ;
					if (cbBombCardType == CT_BOMB_CARD) cbTmpSingleCount += 4 ;
					else if (cbBombCardType == CT_MISSILE_CARD) cbTmpSingleCount += 5 ;
					else if ( 15 == GetCardLogicValue( CardTypeResult[ cbCardType ].cbCardData[ lIndex ][ 0 ] ) ) cbTmpSingleCount += 2;
					else if ( 15 < GetCardLogicValue( CardTypeResult[ cbCardType ].cbCardData[ lIndex ][ 0 ] ) ) cbTmpSingleCount += 3;
                    
                    
					if(cbTmpSingleCount <= cbSingleCardCount)
					{
						OutCardResult.cbCardCount=CardTypeResult[cbCardType].cbEachHandCardCount[lIndex];
						CopyMemory(OutCardResult.cbResultCard, CardTypeResult[cbCardType].cbCardData[lIndex],
                                   CardTypeResult[cbCardType].cbEachHandCardCount[lIndex]*sizeof(BYTE));
						cbSingleCardCount = cbTmpSingleCount ;
                        
						bFindBestCard = true ;
					}
				}
			}
		}
    if (bFindBestCard) return ;
    
    if ( cbHandCardCount == 4 && GetCardLogicValue(cbHandCardData[1]) == 16 && m_cbUserCardCount[m_wBankerUser] == 1 &&
        GetCardLogicValue(cbHandCardData[2]) < GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0]))
    {
        OutCardResult.cbCardCount = 1 ;
        OutCardResult.cbResultCard[0] = cbHandCardData[2] ;
        return ;
    }
    
    if ( AnalyseFourCardType(cbHandCardData, cbHandCardCount, m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser], OutCardResult ) )
    {
        return ;
    }
    
    {
        if(cbLineCardCount+1==cbHandCardCount && CT_SINGLE==GetCardType(cbLineCard, cbLineCardCount))
        {
            OutCardResult.cbCardCount = cbLineCardCount ;
            CopyMemory(OutCardResult.cbResultCard, cbLineCard, cbLineCardCount) ;
        }
        else if(cbThreeLineCardCount+1==cbHandCardCount && CT_THREE_LINE==GetCardType(cbThreeLineCard, cbThreeLineCardCount))
        {
            OutCardResult.cbCardCount = cbThreeLineCardCount ;
            CopyMemory(OutCardResult.cbResultCard, cbThreeLineCard, cbThreeLineCardCount) ;
        }
        else if(cbDoubleLineCount+1==cbHandCardCount && CT_DOUBLE_LINE==GetCardType(cbDoubleLineCard, cbDoubleLineCount))
        {
            OutCardResult.cbCardCount = cbDoubleLineCount ;
            CopyMemory(OutCardResult.cbResultCard, cbDoubleLineCard, cbDoubleLineCount) ;
        }
        else if(cbHandCardCount>2 && cbHandCardData[0]==0x4F && cbHandCardData[1]==0x4E && CT_ERROR!=GetCardType(cbHandCardData+2, cbHandCardCount-2) &&
				CT_FOUR_LINE_TAKE_ONE != GetCardType(cbHandCardData+2, cbHandCardCount-2) && CT_FOUR_LINE_TAKE_TWO != GetCardType(cbHandCardData+2, cbHandCardCount-2))
        {
            OutCardResult.cbCardCount = 2 ;
            OutCardResult.cbResultCard[0] = 0x4F ;
            OutCardResult.cbResultCard[1] = 0x4E ;
        }
        
        if(OutCardResult.cbCardCount>0)
        {
            return ;
        }
    }
    if(cbHandCardCount==3 && GetCardColor(cbHandCardData[0])==0x40 && GetCardColor(cbHandCardData[1])==0x40)
    {
        OutCardResult.cbCardCount = 2 ;
        OutCardResult.cbResultCard[0] = 0x4F ;
        OutCardResult.cbResultCard[1] = 0x4E ;
        return ;
    }
    else if(cbHandCardCount==2 && GetCardColor(cbHandCardData[0])==0x40 && GetCardColor(cbHandCardData[1])==0x40)
    {
        OutCardResult.cbCardCount = 2 ;
        OutCardResult.cbResultCard[0] = 0x4F ;
        OutCardResult.cbResultCard[1] = 0x4E ;
        return ;
    }
    else if(CT_ERROR!=GetCardType(cbHandCardData, cbHandCardCount) && CT_FOUR_LINE_TAKE_ONE!=GetCardType(cbHandCardData, cbHandCardCount) && CT_FOUR_LINE_TAKE_TWO!=GetCardType(cbHandCardData, cbHandCardCount))
    {
        OutCardResult.cbCardCount = cbHandCardCount ;
        CopyMemory(OutCardResult.cbResultCard, cbHandCardData, cbHandCardCount) ;
        return ;
    }
    
    if(cbHandCardCount>=2)
    {
        tagOutCardTypeResult BankerCanOutCardType1[13] ;
        ZeroMemory(BankerCanOutCardType1, sizeof(BankerCanOutCardType1)) ;
        tagOutCardTypeResult BankerCanOutCardType2[13] ;
        ZeroMemory(BankerCanOutCardType2, sizeof(BankerCanOutCardType2)) ;
        
        BYTE cbFirstHandCardType = GetCardType(cbHandCardData, cbHandCardCount-1) ;
        BYTE cbSecondHandCardType = GetCardType(cbHandCardData+1, cbHandCardCount-1) ;
        
        BYTE cbAllBombCardData[MAX_COUNT], cbAllBombCount=0 ;
        GetAllBomCard(cbHandCardData, cbHandCardCount, cbAllBombCardData, cbAllBombCount) ;
        
        if (cbAllBombCount <= 0 && cbFirstHandCardType!=CT_THREE_LINE_TAKE_ONE && cbFirstHandCardType!=CT_THREE_LINE_TAKE_TWO)
        {
            if(cbFirstHandCardType!=CT_ERROR)
                AnalyseOutCardType(m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser], cbHandCardData, cbHandCardCount-1, BankerCanOutCardType1) ;
            if(cbSecondHandCardType!=CT_ERROR)
                AnalyseOutCardType(m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser], cbHandCardData+1, cbHandCardCount-1, BankerCanOutCardType2) ;
            
            if(cbSecondHandCardType!=CT_ERROR && cbSecondHandCardType!=CT_FOUR_LINE_TAKE_ONE && cbSecondHandCardType!= CT_FOUR_LINE_TAKE_TWO &&
               BankerCanOutCardType2[cbSecondHandCardType].cbCardTypeCount==0 && BankerCanOutCardType2[CT_BOMB_CARD].cbCardTypeCount==0)
            {
                OutCardResult.cbCardCount = cbHandCardCount-1 ;
                CopyMemory(OutCardResult.cbResultCard, cbHandCardData+1, cbHandCardCount-1) ;
                return ;
            }
            
            if(cbFirstHandCardType!=CT_ERROR && cbFirstHandCardType!=CT_FOUR_LINE_TAKE_ONE && cbFirstHandCardType!= CT_FOUR_LINE_TAKE_TWO &&
               BankerCanOutCardType1[cbFirstHandCardType].cbCardTypeCount==0 && BankerCanOutCardType2[CT_BOMB_CARD].cbCardTypeCount==0)
            {
                OutCardResult.cbCardCount = cbHandCardCount-1 ;
                CopyMemory(OutCardResult.cbResultCard, cbHandCardData, cbHandCardCount-1) ;
                return ;
            }
            
            if(GetCardLogicValue(cbHandCardData[0])>=GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0]) &&
               CT_ERROR!=cbSecondHandCardType && cbSecondHandCardType!=CT_FOUR_LINE_TAKE_ONE && cbSecondHandCardType!= CT_FOUR_LINE_TAKE_TWO &&
               BankerCanOutCardType2[CT_BOMB_CARD].cbCardTypeCount==0)
            {
                OutCardResult.cbCardCount = 1 ;
                OutCardResult.cbResultCard[0] = cbHandCardData[0] ;
                return ;
            }
            
            if(CT_ERROR!=cbSecondHandCardType && cbSecondHandCardType!=CT_FOUR_LINE_TAKE_ONE && cbSecondHandCardType!= CT_FOUR_LINE_TAKE_TWO &&
               BankerCanOutCardType2[CT_BOMB_CARD].cbCardTypeCount==0)
            {
                OutCardResult.cbCardCount = cbHandCardCount-1 ;
                CopyMemory(OutCardResult.cbResultCard, cbHandCardData+1, cbHandCardCount-1) ;
                return ;
            }
        }
        else
        {
            BYTE cbRemainCard[MAX_COUNT], cbRemainCount=0 ;
            CopyMemory(cbRemainCard, cbHandCardData, cbHandCardCount) ;
            cbRemainCount = cbHandCardCount ;
            RemoveCard(cbAllBombCardData, cbAllBombCount, cbRemainCard, cbRemainCount) ;
            cbRemainCount -= cbAllBombCount ;
            if (GetCardType(cbRemainCard, cbRemainCount) != CT_ERROR)
            {
                OutCardResult.cbCardCount = cbRemainCount ;
                CopyMemory(OutCardResult.cbResultCard, cbRemainCard, cbRemainCount) ;
                return ;
            }
        }
    }
    
    WORD wFriendID = (m_wBankerUser + 1) % GAME_PLAYER ;
    if (1 == m_cbUserCardCount[m_wBankerUser] && cbHandCardCount >= 2 && m_cbUserCardCount[wFriendID] >= 2)
    {
        tagAnalyseResultA MeAnalyseResult ;
        ZeroMemory(&MeAnalyseResult, sizeof(MeAnalyseResult)) ;
        
        AnalysebCardDataA(cbHandCardData, cbHandCardCount, MeAnalyseResult) ;
        
        tagAnalyseResultA FriendAnalyseResult ;
        ZeroMemory(&FriendAnalyseResult, sizeof(FriendAnalyseResult)) ;
        
        AnalysebCardDataA(m_cbAllCardData[wFriendID], m_cbUserCardCount[wFriendID], FriendAnalyseResult) ;
        
        if ((m_cbUserCardCount[wFriendID] == (FriendAnalyseResult.bDoubleCount * 2 + FriendAnalyseResult.bThreeCount * 3 + FriendAnalyseResult.bFourCount * 4) ||
             m_cbUserCardCount[wFriendID] == (FriendAnalyseResult.bDoubleCount * 2 + FriendAnalyseResult.bThreeCount * 3 + FriendAnalyseResult.bFourCount * 4 + 1)) &&
            MeAnalyseResult.bDoubleCount > 0 && FriendAnalyseResult.bDoubleCount > 0)
        {
            BYTE cbMeLeastDoubleCardLogic = GetCardLogicValue(MeAnalyseResult.m_bDCardData[MeAnalyseResult.bDoubleCount*2-2]) ;
            
            BYTE cbFriendLargestDoublecardLogic = GetCardLogicValue(FriendAnalyseResult.m_bDCardData[0]) ;
            
            if (cbMeLeastDoubleCardLogic < 14 && cbMeLeastDoubleCardLogic < cbFriendLargestDoublecardLogic)
            {
                OutCardResult.cbCardCount = 2 ;
                OutCardResult.cbResultCard[0] = MeAnalyseResult.m_bDCardData[MeAnalyseResult.bDoubleCount*2-2] ;
                OutCardResult.cbResultCard[1] = MeAnalyseResult.m_bDCardData[MeAnalyseResult.bDoubleCount*2-1] ;
                return ;
            }
            
        }
    }
    
    //	if(m_cbUserCardCount[m_wBankerUser]<=5)
    {
        tagOutCardTypeResult MeOutCardTypeResult[13] ;
        ZeroMemory(MeOutCardTypeResult, sizeof(MeOutCardTypeResult)) ;
        AnalyseOutCardType(cbHandCardData, cbHandCardCount, MeOutCardTypeResult) ;
        
        WORD wFriendID ;
        for(WORD wChairID=0; wChairID<GAME_PLAYER; ++wChairID)
            if(wChairID!=m_wBankerUser && wMeChairID!=wChairID) wFriendID = wChairID ;
        
        BYTE cbMinSingleCardCount[4] ;
        cbMinSingleCardCount[0]=MAX_COUNT ;
        cbMinSingleCardCount[1]=MAX_COUNT ;
        cbMinSingleCardCount[2]=MAX_COUNT ;
        cbMinSingleCardCount[3]=MAX_COUNT ;
        BYTE cbIndex[4]={0} ;
        BYTE cbOutcardType[4]={CT_ERROR} ;
        BYTE cbMinValue=MAX_COUNT ;
        BYTE cbMinSingleCountInFour=MAX_COUNT ;
        BYTE cbMinCardType=CT_ERROR ;
        BYTE cbMinIndex=0 ;
        
        BYTE cbBankerDoubleCardData[MAX_COUNT], cbBankerDoubleCardCount ;
        GetAllDoubleCard(m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser], cbBankerDoubleCardData, cbBankerDoubleCardCount) ;
        
        for(BYTE cbCardType=CT_DOUBLE; cbCardType<CT_BOMB_CARD; ++cbCardType)
        {
            tagOutCardTypeResult const &tmpCardResult = MeOutCardTypeResult[cbCardType] ;
            
            BYTE cbThisHandCardCount = MAX_COUNT ;
            
            tagOutCardTypeResult BankerCanOutCard[13] ;
            ZeroMemory(BankerCanOutCard, sizeof(BankerCanOutCard)) ;
            
            tagOutCardTypeResult FriendOutCardTypeResult[13] ;
            ZeroMemory(FriendOutCardTypeResult, sizeof(FriendOutCardTypeResult)) ;
            
            for(BYTE i=0; i<tmpCardResult.cbCardTypeCount; ++i)
            {
                if ( cbCardType == CT_DOUBLE )
                {
                    tagAnalyseResultA AnalyseResult ;
                    ZeroMemory( &AnalyseResult,  sizeof( AnalyseResult ) ) ;
                    AnalysebCardDataA( cbHandCardData, cbHandCardCount, AnalyseResult ) ;
                    if ( AnalyseResult.bSignedCount + AnalyseResult.bThreeCount * 3 == cbHandCardCount )
                    {
                        bool bContinue = false ;
                        for ( BYTE cbThreeIndex = 0; cbThreeIndex < AnalyseResult.bThreeCount; ++cbThreeIndex )
                            if ( GetCardValue(  tmpCardResult.cbCardData[i][0] ) == GetCardValue( AnalyseResult.m_bTCardData[3 * cbThreeIndex] ) )
                            {
                                bContinue = true ;
                                break ;
                            }
                        if ( bContinue ) continue ;
                    }
                }
                
                BYTE cbTmpCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, tmpCardResult.cbCardData[i], tmpCardResult.cbEachHandCardCount[i]) ;
                
                if (cbCardType == CT_DOUBLE && cbBankerDoubleCardCount > 0 && GetCardLogicValue(cbBankerDoubleCardData[cbBankerDoubleCardCount-1]) < 10 &&
                    GetCardLogicValue(tmpCardResult.cbCardData[i][0]) < GetCardLogicValue(cbBankerDoubleCardData[cbBankerDoubleCardCount-1]) &&
                    GetCardLogicValue(tmpCardResult.cbCardData[0][0]) >= 10 && GetCardLogicValue(tmpCardResult.cbCardData[0][0]) < 14) continue ;
                
                if(tmpCardResult.cbEachHandCardCount[i]!=cbThisHandCardCount)
                {
                    cbThisHandCardCount = tmpCardResult.cbEachHandCardCount[i] ;
                    AnalyseOutCardType(m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser],
                                       tmpCardResult.cbCardData[i], tmpCardResult.cbEachHandCardCount[i] ,BankerCanOutCard) ;
                    AnalyseOutCardType(m_cbAllCardData[wFriendID], m_cbUserCardCount[wFriendID],
                                       tmpCardResult.cbCardData[i], tmpCardResult.cbEachHandCardCount[i] ,FriendOutCardTypeResult) ;
                }
                
                BYTE cbMaxValue=0 ;
                BYTE Index = 0 ;
                
                BYTE cbCurrentCardType = GetCardType(tmpCardResult.cbCardData[i], cbThisHandCardCount) ;
                if (cbThisHandCardCount != cbHandCardCount && cbCurrentCardType >= CT_SINGLE_LINE && cbCurrentCardType <= CT_THREE_LINE_TAKE_TWO &&
                    ( GetCardLogicValue(tmpCardResult.cbCardData[i][cbThisHandCardCount-1]) > GetCardLogicValue(cbHandCardData[cbHandCardCount-2]) ||
                     GetCardLogicValue(tmpCardResult.cbCardData[i][0]) >= 11 ))
                {
                    BYTE cbRemainCardData[MAX_COUNT], cbRemainCardCount ;
                    CopyMemory(cbRemainCardData, cbHandCardData, cbHandCardCount) ;
                    cbRemainCardCount = cbHandCardCount ;
                    
                    RemoveCard(tmpCardResult.cbCardData[i], cbThisHandCardCount, cbRemainCardData, cbRemainCardCount) ;
                    cbRemainCardCount -= cbThisHandCardCount ;
                    
                    BYTE cbCurrentLargestLogicCard = GetCardLogicValue(tmpCardResult.cbCardData[i][0]) ;
                    
                    if (GetCardType(cbRemainCardData, cbRemainCardCount) == CT_ERROR && (cbCurrentCardType >= CT_THREE_LINE_TAKE_ONE &&
                                                                                         cbCurrentCardType <= CT_THREE_LINE_TAKE_TWO && cbCurrentLargestLogicCard >= 11 && cbThisHandCardCount <=5 ||
                                                                                         cbCurrentCardType == CT_SINGLE_LINE && cbThisHandCardCount <= 6 && cbCurrentLargestLogicCard >= 12 ||
                                                                                         cbCurrentCardType >= CT_DOUBLE_LINE && cbCurrentCardType <= CT_THREE_LINE && cbCurrentLargestLogicCard >= 12 && cbThisHandCardCount <= 8))
                    {
                        if ( cbCurrentCardType >= CT_SINGLE_LINE && cbCurrentCardType <= CT_THREE_LINE &&
                            GetCardLogicValue(tmpCardResult.cbCardData[i][cbThisHandCardCount - 1]) > GetCardLogicValue(cbHandCardData[cbHandCardCount-3]) )
                            continue ;
                        
                        if ( cbCurrentCardType >= CT_THREE_LINE_TAKE_ONE && cbCurrentCardType <= CT_THREE_LINE_TAKE_TWO &&
                            GetCardLogicValue(tmpCardResult.cbCardData[i][0]) > GetCardLogicValue(cbHandCardData[cbHandCardCount-3]) )
                            continue ;
                    }
                }
                
                if((BankerCanOutCard[cbCardType].cbCardTypeCount>0&&FriendOutCardTypeResult[cbCardType].cbCardTypeCount==0) || (BankerCanOutCard[cbCardType].cbCardTypeCount>0 && FriendOutCardTypeResult[cbCardType].cbCardTypeCount>0 &&
                                                                                                                                GetCardLogicValue(FriendOutCardTypeResult[cbCardType].cbCardData[0][0])<=GetCardLogicValue(BankerCanOutCard[cbCardType].cbCardData[0][0])))
                {
                    
                    if( BankerCanOutCard[cbCardType].cbEachHandCardCount[0] > 0 && m_cbUserCardCount[m_wBankerUser]<=BankerCanOutCard[cbCardType].cbEachHandCardCount[0]+1)
                        continue ;
                    
                    if(GetCardLogicValue(tmpCardResult.cbCardData[0][0]) < GetCardLogicValue(BankerCanOutCard[cbCardType].cbCardData[0][0]) &&
                       BankerCanOutCard[cbCardType].cbCardTypeCount > 0)
                        continue ;
                }
                if(tmpCardResult.cbEachHandCardCount[i] != cbHandCardCount)
                {
                    bool bHaveLargeCard=false ;
                    for(BYTE j=0; j<tmpCardResult.cbEachHandCardCount[i]; ++j)
                        if(GetCardLogicValue(tmpCardResult.cbCardData[i][j])>=15) bHaveLargeCard=true ;
                    if(cbCardType!=CT_SINGLE_LINE && cbCardType!=CT_DOUBLE_LINE  && GetCardLogicValue(tmpCardResult.cbCardData[i][0])==14) bHaveLargeCard=true ;
                    
                    if(bHaveLargeCard) continue ;
                }
                
                if(tmpCardResult.cbEachHandCardCount[i]==m_cbUserCardCount[m_wBankerUser] && cbCardType==GetCardType(m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser]) &&
                   GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0])>GetCardLogicValue(tmpCardResult.cbCardData[i][0])) continue ;
                
                for(BYTE j=0; j<4; ++j)
                {
                    if(cbMinSingleCardCount[j]>=cbTmpCount)
                    {
                        cbMinSingleCardCount[j] = cbTmpCount ;
                        cbIndex[j] = i ;
                        cbOutcardType[j] = cbCardType ;
                        break ;
                    }
                }
                
                if(cbMinSingleCountInFour>=cbTmpCount)
                {
                    cbMinCardType = cbCardType ;
                    cbMinSingleCountInFour=cbTmpCount ;
                    cbMinIndex=i ;
                }
            }
        }
        
        if(cbMinSingleCountInFour>=AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, NULL, 0)+3 &&
           m_cbUserCardCount[m_wBankerUser]>4)
            cbMinSingleCountInFour=MAX_COUNT ;
        
        if(cbMinSingleCountInFour!=MAX_COUNT)
        {
            BYTE Index = cbMinIndex ;
            
            for(BYTE i=0; i<4; ++i)
            {
                if(cbOutcardType[i]==cbMinCardType && cbMinSingleCardCount[i]<=cbMinSingleCountInFour &&
                   GetCardLogicValue(MeOutCardTypeResult[cbMinCardType].cbCardData[cbIndex[i]][0])<GetCardLogicValue(MeOutCardTypeResult[cbMinCardType].cbCardData[Index][0]))
                    Index = cbIndex[i] ;
            }
            
            if(cbHandCardCount==3 && GetCardColor(cbHandCardData[0])==0x40 && GetCardColor(cbHandCardData[1])==0x40)
            {
                OutCardResult.cbCardCount = 2 ;
                OutCardResult.cbResultCard[0] = 0x4F ;
                OutCardResult.cbResultCard[1] = 0x4E ;
                return ;
            }
            else if(cbHandCardCount==2 && GetCardColor(cbHandCardData[0])==0x40 && GetCardColor(cbHandCardData[1])==0x40)
            {
                OutCardResult.cbCardCount = 2 ;
                OutCardResult.cbResultCard[0] = 0x4F ;
                OutCardResult.cbResultCard[1] = 0x4E ;
                return ;
            }
            else
            {
                OutCardResult.cbCardCount=MeOutCardTypeResult[cbMinCardType].cbEachHandCardCount[Index];
                CopyMemory(OutCardResult.cbResultCard,MeOutCardTypeResult[cbMinCardType].cbCardData[Index],MeOutCardTypeResult[cbMinCardType].cbEachHandCardCount[Index]*sizeof(BYTE));
                return ;
            }
            return ;
        }
        
        if(OutCardResult.cbCardCount<=0 && m_cbUserCardCount[m_wBankerUser]<=5)
        {
            if(m_cbUserCardCount[m_wBankerUser]==1 && MeOutCardTypeResult[CT_SINGLE].cbCardTypeCount>0)
            {
                BYTE Index=MAX_COUNT ;
                for(BYTE i=0; i<MeOutCardTypeResult[CT_SINGLE].cbCardTypeCount; ++i)
                {
                    if(GetCardLogicValue(MeOutCardTypeResult[CT_SINGLE].cbCardData[i][0])>=GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0]))
                    {
                        Index=i ;
                    }
                    else break ;
                }
                
                if(MAX_COUNT!=Index)
                {
                    OutCardResult.cbCardCount = MeOutCardTypeResult[CT_SINGLE].cbEachHandCardCount[Index] ;
                    CopyMemory(OutCardResult.cbResultCard, MeOutCardTypeResult[CT_SINGLE].cbCardData[Index], OutCardResult.cbCardCount) ;
                    return ;
                }
            }
        }
    }
    
    BYTE cbFirstCard=0 ;
    for(BYTE i=0; i<cbHandCardCount; ++i)
        if(GetCardLogicValue(cbHandCardData[i])<15)
        {
            cbFirstCard = i ;
            break ;
        }
    
    if(cbFirstCard<cbHandCardCount-1)
        AnalyseOutCardType(cbHandCardData+cbFirstCard, cbHandCardCount-cbFirstCard, CardTypeResult) ;
    else
        AnalyseOutCardType(cbHandCardData, cbHandCardCount, CardTypeResult) ;
    
    BYTE cbMinSingleCardCount[4] ;
    cbMinSingleCardCount[0]=MAX_COUNT ;
    cbMinSingleCardCount[1]=MAX_COUNT ;
    cbMinSingleCardCount[2]=MAX_COUNT ;
    cbMinSingleCardCount[3]=MAX_COUNT ;
    BYTE cbIndex[4]={0} ;
    BYTE cbOutcardType[4]={CT_ERROR} ;
    BYTE cbMinValue=MAX_COUNT ;
    BYTE cbMinSingleCountInFour=MAX_COUNT ;
    BYTE cbMinCardType=CT_ERROR ;
    BYTE cbMinIndex=0 ;
    
    BYTE cbBankerSingleCardData[MAX_COUNT] ;
    BYTE cbBankerSingleCardCount=AnalyseSinleCardCount(m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser], NULL, 0, cbBankerSingleCardData) ;
    BYTE cbBankerSingleCardLogic = 0 ;
    if(cbBankerSingleCardCount>=2 && GetCardLogicValue(cbBankerSingleCardData[cbBankerSingleCardCount-2])<=10) cbBankerSingleCardLogic = GetCardLogicValue(cbBankerSingleCardData[cbBankerSingleCardCount-2]) ;
    else if(cbBankerSingleCardCount>=2 && GetCardLogicValue(cbBankerSingleCardData[cbBankerSingleCardCount-1])<=10) cbBankerSingleCardLogic = GetCardLogicValue(cbBankerSingleCardData[cbBankerSingleCardCount-1]) ;
    else if(cbBankerSingleCardCount>0 && GetCardLogicValue(cbBankerSingleCardData[0])<=10) cbBankerSingleCardLogic = GetCardLogicValue(cbBankerSingleCardData[0]) ;
    
    BYTE cbBankerDoubleCardData[MAX_COUNT], cbBankerDoubleCardCount ;
    GetAllDoubleCard(m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser], cbBankerDoubleCardData, cbBankerDoubleCardCount) ;
    
    for(BYTE cbCardType=CT_SINGLE; cbCardType<CT_BOMB_CARD; ++cbCardType)
    {
        tagOutCardTypeResult const &tmpCardResult = CardTypeResult[cbCardType] ;
        for(BYTE i=0; i<tmpCardResult.cbCardTypeCount; ++i)
        {
            if(cbCardType==CT_SINGLE &&  cbBankerSingleCardCount > 0 && GetCardLogicValue(tmpCardResult.cbCardData[i][0])<cbBankerSingleCardLogic) continue ;
            
            if (cbCardType == CT_DOUBLE && cbBankerDoubleCardCount > 0 && GetCardLogicValue(cbBankerDoubleCardData[cbBankerDoubleCardCount-1]) < 10 &&
                GetCardLogicValue(tmpCardResult.cbCardData[i][0]) < GetCardLogicValue(cbBankerDoubleCardData[cbBankerDoubleCardCount-1]) &&
                GetCardLogicValue(tmpCardResult.cbCardData[0][0]) >= 10 && GetCardLogicValue(tmpCardResult.cbCardData[0][0]) < 14) continue ;
            
            if ( tmpCardResult.cbEachHandCardCount[i] != cbHandCardCount && cbCardType >= CT_SINGLE_LINE && cbCardType <= CT_THREE_LINE_TAKE_TWO &&
                ( GetCardLogicValue(tmpCardResult.cbCardData[i][tmpCardResult.cbEachHandCardCount[i]-1]) > GetCardLogicValue(cbHandCardData[cbHandCardCount-2]) ||
                 GetCardLogicValue(tmpCardResult.cbCardData[i][0]) >= 11 ))
            {
                BYTE cbRemainCardData[MAX_COUNT], cbRemainCardCount ;
                CopyMemory(cbRemainCardData, cbHandCardData, cbHandCardCount) ;
                cbRemainCardCount = cbHandCardCount ;
                
                RemoveCard(tmpCardResult.cbCardData[i], tmpCardResult.cbEachHandCardCount[i], cbRemainCardData, cbRemainCardCount) ;
                cbRemainCardCount -= tmpCardResult.cbEachHandCardCount[i] ;
                
                BYTE cbCurrentLargestLogicCard = GetCardLogicValue(tmpCardResult.cbCardData[i][0]) ;
                
                if (GetCardType(cbRemainCardData, cbRemainCardCount) == CT_ERROR && (cbCardType >= CT_THREE_LINE_TAKE_ONE &&
                                                                                     cbCardType <= CT_THREE_LINE_TAKE_TWO && cbCurrentLargestLogicCard >= 11 && tmpCardResult.cbEachHandCardCount[i] <=5 ||
                                                                                     cbCardType == CT_SINGLE_LINE && tmpCardResult.cbEachHandCardCount[i] <= 6 && cbCurrentLargestLogicCard >= 12 ||
                                                                                     cbCardType >= CT_DOUBLE_LINE && cbCardType <= CT_THREE_LINE && cbCurrentLargestLogicCard >= 12 && tmpCardResult.cbEachHandCardCount[i] <= 8))
                {
                    
                    if ( cbCardType >= CT_SINGLE_LINE && cbCardType <= CT_THREE_LINE &&
                        GetCardLogicValue(tmpCardResult.cbCardData[i][tmpCardResult.cbEachHandCardCount[i] - 1]) > GetCardLogicValue(cbHandCardData[cbHandCardCount-3]) )
                        continue ;
                    
                    if ( cbCardType >= CT_THREE_LINE_TAKE_ONE && cbCardType <= CT_THREE_LINE_TAKE_TWO &&
                        GetCardLogicValue(tmpCardResult.cbCardData[i][0]) > GetCardLogicValue(cbHandCardData[cbHandCardCount-3]) )
                        continue ;
                }
            }
            
            BYTE cbTmpCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, tmpCardResult.cbCardData[i], tmpCardResult.cbEachHandCardCount[i]) ;
            
            BYTE cbMaxValue=0 ;
            BYTE Index = 0 ;
            
            for(BYTE j=0; j<4; ++j)
            {
                if(cbMinSingleCardCount[j]>=cbTmpCount)
                {
                    cbMinSingleCardCount[j] = cbTmpCount ;
                    cbIndex[j] = i ;
                    cbOutcardType[j] = cbCardType ;
                    break ;
                }
            }
            
            if(cbMinSingleCountInFour>=cbTmpCount)
            {
                cbMinCardType = cbCardType ;
                cbMinSingleCountInFour=cbTmpCount ;
                cbMinIndex=i ;
            }
        }
    }
    
    if(cbMinSingleCountInFour!=MAX_COUNT)
    {
        BYTE Index = cbMinIndex ;
        
        for(BYTE i=0; i<4; ++i)
        {
            if(cbOutcardType[i]==cbMinCardType && cbMinSingleCardCount[i]<=cbMinSingleCountInFour &&
               GetCardLogicValue(CardTypeResult[cbMinCardType].cbCardData[cbIndex[i]][0])<GetCardLogicValue(CardTypeResult[cbMinCardType].cbCardData[Index][0]))
                Index = cbIndex[i] ;
        }
        
        if(cbHandCardCount==3 && GetCardColor(cbHandCardData[0])==0x40 && GetCardColor(cbHandCardData[1])==0x40)
        {
            OutCardResult.cbCardCount = 2 ;
            OutCardResult.cbResultCard[0] = 0x4F ;
            OutCardResult.cbResultCard[1] = 0x4E ;
            return ;
        }
        else if(cbHandCardCount==2 && GetCardColor(cbHandCardData[0])==0x40 && GetCardColor(cbHandCardData[1])==0x40)
        {
            OutCardResult.cbCardCount = 2 ;
            OutCardResult.cbResultCard[0] = 0x4F ;
            OutCardResult.cbResultCard[1] = 0x4E ;
            return ;
        }
        else
        {
            OutCardResult.cbCardCount=CardTypeResult[cbMinCardType].cbEachHandCardCount[Index];
            CopyMemory(OutCardResult.cbResultCard,CardTypeResult[cbMinCardType].cbCardData[Index],CardTypeResult[cbMinCardType].cbEachHandCardCount[Index]*sizeof(BYTE));
            return ;
        }
        
        return ;
    }
    else if (CardTypeResult[CT_BOMB_CARD].cbCardTypeCount > 0)
    {
        
    }
    
    BYTE cbAllSingleCardData[MAX_COUNT], cbAllSingleCardCount ;
    cbAllSingleCardCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, NULL, 0, cbAllSingleCardData) ;
    
    if ( cbAllSingleCardCount > 0 )
    {
        if ( 1 == m_cbUserCardCount[m_wBankerUser] )
        {
            OutCardResult.cbCardCount = 1 ;
            OutCardResult.cbResultCard[0] = cbAllSingleCardData[0] ;
        }
        else
        {
            OutCardResult.cbCardCount = 1 ;
            OutCardResult.cbResultCard[0] = cbAllSingleCardData[cbAllSingleCardCount-1] ;
        }
        return ;
    }
    
    OutCardResult.cbCardCount = 1 ;
    OutCardResult.cbResultCard[0] = cbHandCardData[cbHandCardCount-1] ;
    return ;
}

void DDZCGameLogicSingle::UpsideOfBankerOutCard(const BYTE cbHandCardData[], BYTE cbHandCardCount, WORD wOutCardUser, const BYTE cbTurnCardData[], BYTE cbTurnCardCount, tagOutCardResult & OutCardResult)
{
	tagOutCardTypeResult CardTypeResult[12+1] ;
	ZeroMemory(CardTypeResult, sizeof(CardTypeResult)) ;
    
	ZeroMemory(&OutCardResult, sizeof(OutCardResult)) ;
    
	BYTE cbOutCardType = GetCardType(cbTurnCardData, cbTurnCardCount) ;
    
	if (m_cbUserCardCount[m_wBankerUser] == 1 && wOutCardUser != m_wBankerUser && CT_SINGLE == cbOutCardType)
	{
		BYTE cbSingleCardData[MAX_COUNT] ;
		BYTE cbSingleCardCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, NULL, 0, cbSingleCardData) ;
        
		WORD wFriendID = (m_wBankerUser+1) % GAME_PLAYER ;
		WORD wMeID = (wFriendID+1) % GAME_PLAYER ;
        
		BYTE cbFriendLargestLogicCard = GetCardLogicValue(m_cbAllCardData[wFriendID][0]) ;
		BYTE cbMeLargestLogicCard = GetCardLogicValue(cbHandCardData[0]) ;
		BYTE cbTurnLogicCard = GetCardLogicValue(cbTurnCardData[0]) ;
        
		if (cbSingleCardCount == cbHandCardCount && cbFriendLargestLogicCard > cbTurnLogicCard && cbMeLargestLogicCard > cbTurnLogicCard)
		{
			printf("ￖﾻￊﾣﾵﾥￅￆ\n");
			OutCardResult.cbCardCount = 1 ;
			OutCardResult.cbResultCard[0] = cbHandCardData[0] ;
            
			return ;
		}
	}
    
	tagOutCardTypeResult BankerOutCardTypeResult[13] ;
	ZeroMemory(BankerOutCardTypeResult, sizeof(BankerOutCardTypeResult)) ;
    
	AnalyseOutCardType(m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser], BankerOutCardTypeResult) ;
	AnalyseOutCardType(cbHandCardData,cbHandCardCount,cbTurnCardData,cbTurnCardCount, CardTypeResult) ;
    
	if(cbHandCardCount==CardTypeResult[CT_BOMB_CARD].cbEachHandCardCount[0] && (cbOutCardType<CT_BOMB_CARD ||
                                                                                GetCardLogicValue(CardTypeResult[CT_BOMB_CARD].cbCardData[0][0])>GetCardLogicValue(cbTurnCardData[0])))
	{
		printf("ￖﾻￊﾣￕﾨﾵﾯ\n");
		OutCardResult.cbCardCount = CardTypeResult[CT_BOMB_CARD].cbEachHandCardCount[0] ;
		CopyMemory(OutCardResult.cbResultCard,  CardTypeResult[CT_BOMB_CARD].cbCardData, OutCardResult.cbCardCount) ;
        
		return ;
	}
	else if(cbHandCardCount>2 && cbHandCardData[0]==0x4F && cbHandCardData[1]==0x4E && CT_ERROR!=GetCardType(cbHandCardData+2, cbHandCardCount-2) &&
            CT_FOUR_LINE_TAKE_ONE != GetCardType(cbHandCardData+2, cbHandCardCount-2) && CT_FOUR_LINE_TAKE_TWO != GetCardType(cbHandCardData+2, cbHandCardCount-2))
	{
		printf("ￋﾫￍ￵ￕﾨﾵﾯﾺￍￒﾻￊￖ\n");
		OutCardResult.cbCardCount = 2 ;
		OutCardResult.cbResultCard[0] = 0x4F ;
		OutCardResult.cbResultCard[1] = 0x4E ;
		return ;
	}
    
	BYTE cbRemainCard[MAX_COUNT], cbRemainCount=0;
	BYTE cbAllBombCard[MAX_COUNT], cbAllBombCount=0 ;
	GetAllBomCard(cbHandCardData, cbHandCardCount, cbAllBombCard, cbAllBombCount) ;
    
	if(cbAllBombCount>0 && m_wBankerUser==wOutCardUser)
	{
		CopyMemory(cbRemainCard, cbHandCardData, cbHandCardCount) ;
		cbRemainCount = cbHandCardCount ;
		RemoveCard(cbAllBombCard, cbAllBombCount, cbRemainCard, cbRemainCount) ;
		cbRemainCount -= cbAllBombCount ;
        
		if(CT_ERROR != GetCardType(cbRemainCard, cbRemainCount) ||
           (2==cbRemainCount && GetCardLogicValue(cbRemainCard[0])>GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0])))
		{
			if((cbOutCardType<CT_BOMB_CARD || GetCardLogicValue(cbAllBombCard[0])>GetCardLogicValue(cbTurnCardData[0])) &&
               ( CardTypeResult[cbOutCardType].cbCardTypeCount <= 0 || CT_ERROR != GetCardType(cbRemainCard, cbRemainCount)) )
			{
				if(GetCardColor(cbAllBombCard[0])==0x40)
				{
					OutCardResult.cbCardCount = 2 ;
					OutCardResult.cbResultCard[0] = 0x4F ;
					OutCardResult.cbResultCard[1] = 0x4E ;
					return ;
				}
				else
				{
					BYTE cbBankerAllBombCard[MAX_COUNT], cbBankerAllBombCardCount ;
					GetAllBomCard( m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser], cbBankerAllBombCard, cbBankerAllBombCardCount) ;
                    
					if ( !CompareCard( cbTurnCardData, cbRemainCard, cbTurnCardCount, cbRemainCount) ||  cbBankerAllBombCardCount <= 0 ||
						GetCardLogicValue( cbAllBombCard[0] ) > GetCardLogicValue( cbBankerAllBombCard[0] ) )
					{
						OutCardResult.cbCardCount = 4 ;
						CopyMemory(OutCardResult.cbResultCard, cbAllBombCard, 4) ;
						return ;
					}
				}
			}
		}
	}
    
	printf("￀￠￐ￍ=%dﾣﾬￅￆﾴ￳￐ﾡ=%d \n",GetCardType(cbHandCardData, cbHandCardCount),CompareCard(cbTurnCardData, cbHandCardData, cbTurnCardCount, cbHandCardCount));
    
	if ( GetCardType(cbHandCardData, cbHandCardCount) != CT_FOUR_LINE_TAKE_ONE && GetCardType(cbHandCardData, cbHandCardCount) != CT_FOUR_LINE_TAKE_TWO
		&&GetCardType(cbHandCardData,cbHandCardCount) != CT_ERROR && CompareCard(cbTurnCardData, cbHandCardData, cbTurnCardCount, cbHandCardCount))
	{
		printf("ￖﾻￓ￐ￒﾻￊￖￅￆ\n");
		OutCardResult.cbCardCount = cbHandCardCount ;
		CopyMemory(OutCardResult.cbResultCard, cbHandCardData, cbHandCardCount) ;
        
		return ;
	}
    
	if (1 == m_cbUserCardCount[m_wBankerUser] && cbHandCardCount >= 2 && cbOutCardType == CT_DOUBLE)
	{
		tagAnalyseResultA AnalyseResult ;
		ZeroMemory(&AnalyseResult, sizeof(AnalyseResult));
        
		AnalysebCardDataA(cbHandCardData, cbHandCardCount, AnalyseResult) ;
        
		if (cbHandCardCount == (AnalyseResult.bDoubleCount * 2 + AnalyseResult.bThreeCount * 3 + AnalyseResult.bFourCount * 4) ||
			cbHandCardCount == (AnalyseResult.bDoubleCount * 2 + AnalyseResult.bThreeCount * 3 + AnalyseResult.bFourCount * 4 + 1))
		{
			for (int nIndex = AnalyseResult.bDoubleCount-1; nIndex>=0 ; --nIndex)
			{
				if (GetCardLogicValue(AnalyseResult.m_bDCardData[nIndex*2]) > GetCardLogicValue(cbTurnCardData[0]))
				{
					OutCardResult.cbCardCount = 2 ;
					OutCardResult.cbResultCard[0] = AnalyseResult.m_bDCardData[nIndex*2] ;
					OutCardResult.cbResultCard[1] = AnalyseResult.m_bDCardData[nIndex*2+1] ;
					return ;
				}
			}
            
			if (AnalyseResult.bFourCount > 0)
			{
				BYTE cbLestBombIndex = AnalyseResult.bFourCount-1 ;
                
				OutCardResult.cbCardCount = 4 ;
				OutCardResult.cbResultCard[0] = AnalyseResult.m_bFCardData[cbLestBombIndex*4] ;
				OutCardResult.cbResultCard[1] = AnalyseResult.m_bFCardData[cbLestBombIndex*4+1] ;
				OutCardResult.cbResultCard[2] = AnalyseResult.m_bFCardData[cbLestBombIndex*4+2] ;
				OutCardResult.cbResultCard[3] = AnalyseResult.m_bFCardData[cbLestBombIndex*4+3] ;
                
				return ;
			}
            
		}
        
		if ( wOutCardUser != m_wBankerUser )
		{
			tagAnalyseResultA FriendAnalyseResult ;
			ZeroMemory( &FriendAnalyseResult, sizeof( FriendAnalyseResult ) ) ;
            
			AnalysebCardDataA( m_cbAllCardData[wOutCardUser], m_cbUserCardCount[wOutCardUser], FriendAnalyseResult ) ;
            
			if (m_cbUserCardCount[wOutCardUser] == (FriendAnalyseResult.bDoubleCount * 2 + FriendAnalyseResult.bThreeCount * 3 + FriendAnalyseResult.bFourCount * 4) ||
				m_cbUserCardCount[wOutCardUser] == (FriendAnalyseResult.bDoubleCount * 2 + FriendAnalyseResult.bThreeCount * 3 + FriendAnalyseResult.bFourCount * 4 + 1))
			{
				return ;
			}
            
			tagOutCardTypeResult FriendCardTypeResult[12+1] ;
			ZeroMemory( FriendCardTypeResult, sizeof( FriendCardTypeResult ) ) ;
            
			AnalyseOutCardType( m_cbAllCardData[wOutCardUser], m_cbUserCardCount[wOutCardUser], FriendCardTypeResult ) ;
            
			for ( BYTE cbLineCardIdx = 0; cbLineCardIdx < FriendCardTypeResult[CT_SINGLE_LINE].cbCardTypeCount; ++cbLineCardIdx )
			{
				BYTE cbRemainCardData[MAX_COUNT], cbRemainCardCount ;
                
				cbRemainCardCount = m_cbUserCardCount[wOutCardUser] ;
				CopyMemory( cbRemainCardData, m_cbAllCardData[wOutCardUser], cbRemainCardCount ) ;
				RemoveCard( FriendCardTypeResult[CT_SINGLE_LINE].cbCardData[cbLineCardIdx],  FriendCardTypeResult[CT_SINGLE_LINE].cbEachHandCardCount[cbLineCardIdx],
                           cbRemainCardData, cbRemainCardCount ) ;
                
				cbRemainCardCount -= FriendCardTypeResult[CT_SINGLE_LINE].cbEachHandCardCount[cbLineCardIdx] ;
                
				AnalysebCardDataA( cbRemainCardData, cbRemainCardCount, FriendAnalyseResult ) ;
                
				if (cbRemainCardCount == (FriendAnalyseResult.bDoubleCount * 2 + FriendAnalyseResult.bThreeCount * 3 + FriendAnalyseResult.bFourCount * 4) ||
					cbRemainCardCount == (FriendAnalyseResult.bDoubleCount * 2 + FriendAnalyseResult.bThreeCount * 3 + FriendAnalyseResult.bFourCount * 4 + 1))
				{
					return ;
				}
			}
            
			for ( BYTE cbLineCardIdx = 0; cbLineCardIdx < FriendCardTypeResult[CT_DOUBLE_LINE].cbCardTypeCount; ++cbLineCardIdx )
			{
				BYTE cbRemainCardData[MAX_COUNT], cbRemainCardCount ;
                
				cbRemainCardCount = m_cbUserCardCount[wOutCardUser] ;
				CopyMemory( cbRemainCardData, m_cbAllCardData[wOutCardUser], cbRemainCardCount ) ;
				RemoveCard( FriendCardTypeResult[CT_SINGLE_LINE].cbCardData[cbLineCardIdx],  FriendCardTypeResult[CT_SINGLE_LINE].cbEachHandCardCount[cbLineCardIdx],
                           cbRemainCardData, cbRemainCardCount ) ;
                
				cbRemainCardCount -= FriendCardTypeResult[CT_SINGLE_LINE].cbEachHandCardCount[cbLineCardIdx] ;
                
				AnalysebCardDataA( cbRemainCardData, cbRemainCardCount, FriendAnalyseResult ) ;
                
				if (cbRemainCardCount == (FriendAnalyseResult.bDoubleCount * 2 + FriendAnalyseResult.bThreeCount * 3 + FriendAnalyseResult.bFourCount * 4) ||
					cbRemainCardCount == (FriendAnalyseResult.bDoubleCount * 2 + FriendAnalyseResult.bThreeCount * 3 + FriendAnalyseResult.bFourCount * 4 + 1))
				{
					return ;
				}
			}
            
            
		}
	}
    
	if( m_wBankerUser != wOutCardUser && ! CompareCard( cbTurnCardData, m_cbAllCardData[ m_wBankerUser ], cbTurnCardCount, m_cbUserCardCount[ m_wBankerUser ] ) )
	{
		printf("ﾶￔﾼￒ﾿￉ﾷ￱ﾳ￶ￍ￪\n");
        
		bool bBankerCanOut = false ;
		tagOutCardTypeResult BankerOutCardResult[12+1] ;
		ZeroMemory(BankerOutCardResult, sizeof(BankerOutCardResult)) ;
        
		AnalyseOutCardType(m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser], cbTurnCardData, cbTurnCardCount, BankerOutCardResult) ;
		for(BYTE cbCardType=CT_SINGLE; cbCardType<=CT_MISSILE_CARD; ++cbCardType) if(BankerOutCardResult[cbCardType].cbCardTypeCount>0) bBankerCanOut = true ;
        
		if(!bBankerCanOut)
		{
			WORD wFriendChairID = (m_wBankerUser+1)%GAME_PLAYER ;
            
			tagOutCardTypeResult FriendCardTypeResult[12+1] ;
			ZeroMemory(FriendCardTypeResult, sizeof(FriendCardTypeResult)) ;
			AnalyseOutCardType(m_cbAllCardData[wFriendChairID], m_cbUserCardCount[wFriendChairID], FriendCardTypeResult) ;
            
			for(BYTE cbCardType=CT_SINGLE; cbCardType<=CT_MISSILE_CARD; ++cbCardType)
				if(FriendCardTypeResult[cbCardType].cbCardTypeCount>0)
				{
					for(long lIndex=0; lIndex<FriendCardTypeResult[cbCardType].cbCardTypeCount; ++lIndex)
					{
						if(TestOutAllCard(wFriendChairID, FriendCardTypeResult[cbCardType].cbCardData[lIndex], FriendCardTypeResult[cbCardType].cbEachHandCardCount[lIndex], true))
						{
							return ;
						}
					}
				}
		}
	}
    
	if (GetCardType(m_cbAllCardData[(m_wBankerUser + 1) % GAME_PLAYER], m_cbUserCardCount[(m_wBankerUser + 1) % GAME_PLAYER]) == GetCardType(cbTurnCardData, cbTurnCardCount) &&
		CompareCard(cbTurnCardData, m_cbAllCardData[(m_wBankerUser + 1) % GAME_PLAYER], cbTurnCardCount, m_cbUserCardCount[(m_wBankerUser + 1) % GAME_PLAYER]) &&
		!CompareCard(cbTurnCardData, m_cbAllCardData[m_wBankerUser], cbTurnCardCount, m_cbUserCardCount[m_wBankerUser]))
		return ;
    
	if (CompareCard(cbTurnCardData, m_cbAllCardData[(m_wBankerUser + 1) % GAME_PLAYER], cbTurnCardCount, m_cbUserCardCount[(m_wBankerUser + 1) % GAME_PLAYER]) &&
		!CompareCard(cbTurnCardData, m_cbAllCardData[m_wBankerUser], cbTurnCardCount, m_cbUserCardCount[m_wBankerUser])) return ;
    
	printf("ￅ￐ﾶￏ﾿￉ﾷ￱ﾳ￶ￍ￪\n");
	BYTE cbSingleCardCount = MAX_COUNT+CT_MISSILE_CARD ;
	bool bFindBestCard = false ;
	for(BYTE cbCardType=CT_SINGLE; cbCardType<=CT_MISSILE_CARD; ++cbCardType)
		if(CardTypeResult[cbCardType].cbCardTypeCount>0)
		{
			for(long lIndex=0; lIndex<CardTypeResult[cbCardType].cbCardTypeCount; ++lIndex)
			{
				WORD wMeChairID = (m_wBankerUser+2)%GAME_PLAYER ;
                
				if(TestOutAllCard(wMeChairID, CardTypeResult[cbCardType].cbCardData[lIndex], CardTypeResult[cbCardType].cbEachHandCardCount[lIndex], false))
				{
					BYTE cbTmpSingleCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, CardTypeResult[cbCardType].cbCardData[lIndex],
                                                                  CardTypeResult[cbCardType].cbEachHandCardCount[lIndex]) ;
                    
					if (cbTmpSingleCount >= MAX_COUNT) continue ;
                    
					BYTE cbBombCardType = GetCardType(CardTypeResult[cbCardType].cbCardData[lIndex], CardTypeResult[cbCardType].cbEachHandCardCount[lIndex]) ;
					if (cbBombCardType == CT_BOMB_CARD) cbTmpSingleCount += 4 ;
					else if (cbBombCardType == CT_MISSILE_CARD) cbTmpSingleCount += 5 ;
                    
					if(cbTmpSingleCount <= cbSingleCardCount)
					{
						OutCardResult.cbCardCount=CardTypeResult[cbCardType].cbEachHandCardCount[lIndex];
						CopyMemory(OutCardResult.cbResultCard, CardTypeResult[cbCardType].cbCardData[lIndex],
                                   CardTypeResult[cbCardType].cbEachHandCardCount[lIndex]*sizeof(BYTE));
						cbSingleCardCount = cbTmpSingleCount ;
                        
						bFindBestCard = true ;
					}
				}
			}
		}
    if (bFindBestCard) return ;
    
    if( m_cbUserCardCount[m_wBankerUser]<=5 && wOutCardUser!=m_wBankerUser &&
       (BankerOutCardTypeResult[cbOutCardType].cbCardTypeCount==0 ||
        GetCardLogicValue(BankerOutCardTypeResult[cbOutCardType].cbCardData[0][0])<=GetCardLogicValue(cbTurnCardData[0])) &&
       CardTypeResult[cbOutCardType].cbEachHandCardCount[0]!=cbHandCardCount)//ﾲﾻￄￜￒﾻﾴￎﾳ￶ￍ￪
    {
        return ;
    }
    
    if(m_cbUserCardCount[m_wBankerUser]<=5 && CardTypeResult[cbOutCardType].cbCardTypeCount>0 && cbOutCardType!=CT_BOMB_CARD &&
       ((GetCardLogicValue(cbTurnCardData[0])<12 && wOutCardUser!=m_wBankerUser && BankerOutCardTypeResult[cbOutCardType].cbCardTypeCount>0) ||
        (wOutCardUser==m_wBankerUser)))
    {
        BYTE Index = cbOutCardType == CT_SINGLE ? 0 : CardTypeResult[cbOutCardType].cbCardTypeCount - 1 ;
        
        BYTE cbThisOutTypeMinSingleCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, CardTypeResult[cbOutCardType].cbCardData[0], CardTypeResult[cbOutCardType].cbEachHandCardCount[0]) ;
        BYTE cbBestIndex = 255 ;
        for(BYTE i=0; i<CardTypeResult[cbOutCardType].cbCardTypeCount; ++i)
        {
            BYTE cbTmpSingleCardCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, CardTypeResult[cbOutCardType].cbCardData[i], CardTypeResult[cbOutCardType].cbEachHandCardCount[i]) ;
            if((BankerOutCardTypeResult[cbOutCardType].cbCardTypeCount>0 &&
                GetCardLogicValue(CardTypeResult[cbOutCardType].cbCardData[i][0])>=GetCardLogicValue(BankerOutCardTypeResult[cbOutCardType].cbCardData[0][0]) ||
                BankerOutCardTypeResult[cbOutCardType].cbCardTypeCount==0) &&
               cbTmpSingleCardCount<=cbThisOutTypeMinSingleCount)
            {
                cbBestIndex = i ;
                cbThisOutTypeMinSingleCount = cbTmpSingleCardCount ;
            }
            
            if((BankerOutCardTypeResult[cbOutCardType].cbCardTypeCount>0 &&
                GetCardLogicValue(CardTypeResult[cbOutCardType].cbCardData[i][0])>=GetCardLogicValue(BankerOutCardTypeResult[cbOutCardType].cbCardData[0][0]) ||
                BankerOutCardTypeResult[cbOutCardType].cbCardTypeCount==0))
                Index = i ;
            else break ;
        }
        
        if(cbBestIndex!=255)
        {
            OutCardResult.cbCardCount = CardTypeResult[cbOutCardType].cbEachHandCardCount[cbBestIndex] ;
            CopyMemory(OutCardResult.cbResultCard, CardTypeResult[cbOutCardType].cbCardData[cbBestIndex], OutCardResult.cbCardCount) ;
        }
        else
        {
            OutCardResult.cbCardCount = CardTypeResult[cbOutCardType].cbEachHandCardCount[Index] ;
            CopyMemory(OutCardResult.cbResultCard, CardTypeResult[cbOutCardType].cbCardData[Index], OutCardResult.cbCardCount) ;
        }
        
        return ;
    }
    
    if (CT_SINGLE == cbOutCardType && CardTypeResult[cbOutCardType].cbCardTypeCount > 0)
    {
        BYTE cbMeSingleCardData[MAX_COUNT], cbMeSingleCardCount ;
        BYTE cbBankerSingleCardData[MAX_COUNT], cbBankerSingleCardCount ;
        
        cbMeSingleCardCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, NULL, 0, cbMeSingleCardData) ;
        cbBankerSingleCardCount = AnalyseSinleCardCount(m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser], NULL, 0, cbBankerSingleCardData) ;
        
        if (cbBankerSingleCardCount > 0 && cbMeSingleCardCount > 0 && GetCardLogicValue(cbBankerSingleCardData[cbBankerSingleCardCount-1]) <= 10)
        {
            if (cbBankerSingleCardCount >= 2 && GetCardValue(cbBankerSingleCardData[cbBankerSingleCardCount-2]) <= 10)
            {
                for (int nMeIndex = cbMeSingleCardCount-1; nMeIndex >=0 ; --nMeIndex)
                    if (GetCardLogicValue(cbMeSingleCardData[nMeIndex]) > GetCardLogicValue(cbTurnCardData[0]) &&
                        GetCardLogicValue(cbMeSingleCardData[nMeIndex]) >= GetCardLogicValue(cbBankerSingleCardData[cbBankerSingleCardCount-2]) &&
                        GetCardLogicValue(cbMeSingleCardData[nMeIndex]) <= 15)
                    {
                        OutCardResult.cbCardCount = 1 ;
                        OutCardResult.cbResultCard[0] = cbMeSingleCardData[nMeIndex] ;
                        
                        return ;
                    }
            }
            
            for (int nMeIndex = cbMeSingleCardCount-1; nMeIndex >=0 ; --nMeIndex)
                if (GetCardLogicValue(cbMeSingleCardData[nMeIndex]) > GetCardLogicValue(cbTurnCardData[0]) &&
                    GetCardLogicValue(cbMeSingleCardData[nMeIndex]) >= GetCardLogicValue(cbBankerSingleCardData[cbBankerSingleCardCount-1]) &&
                    GetCardLogicValue(cbMeSingleCardData[nMeIndex]) <= 15)
                {
                    OutCardResult.cbCardCount = 1 ;
                    OutCardResult.cbResultCard[0] = cbMeSingleCardData[nMeIndex] ;
                    
                    return ;
                }
        }
    }
    
    BYTE cbMinSingleCardCount[4] ;
    cbMinSingleCardCount[0]=MAX_COUNT ;
    cbMinSingleCardCount[1]=MAX_COUNT ;
    cbMinSingleCardCount[2]=MAX_COUNT ;
    cbMinSingleCardCount[3]=MAX_COUNT ;
    BYTE cbIndex[4]={0} ;
    BYTE cbMinSingleCountInFour=MAX_COUNT ;
    tagOutCardTypeResult const &CanOutCard = CardTypeResult[cbOutCardType] ;
    
    for(BYTE i=0; i<CanOutCard.cbCardTypeCount; ++i)
    {
        BYTE cbTmpCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount,CanOutCard.cbCardData[i], CanOutCard.cbEachHandCardCount[i]) ;
        BYTE cbMaxValue=0 ;
        BYTE Index = 0 ;
        
        for(BYTE j=0; j<4; ++j)
        {
            if(cbMinSingleCardCount[j]>=cbTmpCount)
            {
                cbMinSingleCardCount[j] = cbTmpCount ;
                cbIndex[j] = i ;
                break ;
            }
        }
        
    }
    
    for(BYTE i=0; i<4; ++i)
        if(cbMinSingleCountInFour>cbMinSingleCardCount[i]) cbMinSingleCountInFour = cbMinSingleCardCount[i] ;
    
    
    BYTE cbOriginSingleCardCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount,NULL,0) ;
    
    BYTE cbBankerDoubleCardData[MAX_COUNT], cbBankerDoubleCardCount ;
    GetAllDoubleCard(m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser], cbBankerDoubleCardData, cbBankerDoubleCardCount) ;
    
    bool bFriendOut = m_wBankerUser!=wOutCardUser ;
    if(bFriendOut)
    {
        if (GetCardType(m_cbAllCardData[(1 + m_wBankerUser) % GAME_PLAYER], m_cbUserCardCount[(1 + m_wBankerUser) % GAME_PLAYER]) != CT_ERROR) return ;
        
        if(CanOutCard.cbCardTypeCount>0 && CanOutCard.cbCardType < CT_BOMB_CARD)
        {
            BYTE cbBankerSingleCardData[MAX_COUNT] ;
            BYTE cbBankerSingleCardCount=AnalyseSinleCardCount(m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser], NULL, 0, cbBankerSingleCardData) ;
            BYTE cbBankerSingleCardLogic = 0 ;
            
            if(cbBankerSingleCardCount>=2 && GetCardLogicValue(cbBankerSingleCardData[cbBankerSingleCardCount-2])<=10) cbBankerSingleCardLogic = GetCardLogicValue(cbBankerSingleCardData[cbBankerSingleCardCount-2]) ;
            else if(cbBankerSingleCardCount>=2 && GetCardLogicValue(cbBankerSingleCardData[cbBankerSingleCardCount-1])<=10) cbBankerSingleCardLogic = GetCardLogicValue(cbBankerSingleCardData[cbBankerSingleCardCount-1]) ;
            else if(cbBankerSingleCardCount>0 && GetCardLogicValue(cbBankerSingleCardData[0])<=10) cbBankerSingleCardLogic = GetCardLogicValue(cbBankerSingleCardData[0]) ;
            
            BYTE cbMinLogicCardValue = GetCardLogicValue(0x4F)+1 ;
            bool bFindCard = false ;
            BYTE cbCanOutIndex=0 ;
            for(BYTE i=0; i<4; ++i)
            {
                BYTE Index = cbIndex[i] ;
                
                if ( CanOutCard.cbCardType >= CT_THREE &&  CanOutCard.cbCardType <= CT_MISSILE_CARD && GetCardLogicValue(CanOutCard.cbCardData[Index][0]) >= 7 &&
                    CanOutCard.cbEachHandCardCount[Index] <=5 )
                    continue ;
                
                bool bCanOut = false ;
                if(cbOutCardType==CT_SINGLE && cbBankerSingleCardCount > 0 && GetCardLogicValue(CanOutCard.cbCardData[Index][0]) >= cbBankerSingleCardLogic &&
                   GetCardLogicValue(cbTurnCardData[0]) < 14 && cbMinSingleCardCount[i] < cbOriginSingleCardCount &&
                   GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0]) > GetCardLogicValue(cbTurnCardData[0]))
                    bCanOut = true ;
                
                
                if(bCanOut ||
                   ((cbMinSingleCardCount[i]<cbOriginSingleCardCount+3 &&  (cbMinSingleCardCount[i]<=cbMinSingleCountInFour || cbMinSingleCardCount[i]<=cbMinSingleCountInFour+1 &&
                                                                            CanOutCard.cbCardType >= CT_THREE_LINE_TAKE_ONE && CanOutCard.cbCardType <= CT_THREE_LINE_TAKE_TWO ) &&
                     (GetCardLogicValue(CanOutCard.cbCardData[Index][0])<=11 || (cbMinSingleCardCount[i]<cbOriginSingleCardCount)&&GetCardLogicValue(CanOutCard.cbCardData[Index][0])<=13)) &&
                    cbMinLogicCardValue>GetCardLogicValue(CanOutCard.cbCardData[Index][0]) && cbHandCardCount>5))
                {
                    
                    bool bNoLargeCard = true ;
                    for(BYTE k=3; k<CanOutCard.cbEachHandCardCount[Index]; ++k)
                    {
                        if(GetCardLogicValue(CanOutCard.cbCardData[Index][k])>=15 &&
                           CanOutCard.cbEachHandCardCount[Index]!=cbHandCardCount) bNoLargeCard = false ;
                    }
                    if(bNoLargeCard)
                    {
                        bFindCard = true ;
                        cbCanOutIndex = Index ;
                        cbMinLogicCardValue = GetCardLogicValue(CanOutCard.cbCardData[Index][0]) ;
                    }
                }
                else if(cbHandCardCount<5 && cbMinSingleCardCount[i]<cbOriginSingleCardCount+4 && cbMinSingleCardCount[i]<=cbMinSingleCountInFour &&
						cbMinLogicCardValue>GetCardLogicValue(CanOutCard.cbCardData[Index][0]))
                {
                    if ( GetCardLogicValue( CanOutCard.cbCardData[Index][0] ) >= 16 && GetCardLogicValue( cbTurnCardData[0] ) >= 15 )
                        continue ;
                    
                    bFindCard = true ;
                    cbCanOutIndex = Index ;
                    cbMinLogicCardValue = GetCardLogicValue(CanOutCard.cbCardData[Index][0]) ;
                }
            }
            
            if(bFindCard)
            {
                
                OutCardResult.cbCardCount=CanOutCard.cbEachHandCardCount[cbCanOutIndex];
                CopyMemory(OutCardResult.cbResultCard,CanOutCard.cbCardData[cbCanOutIndex],CanOutCard.cbEachHandCardCount[cbCanOutIndex]*sizeof(BYTE));
                
                return ;
            }
            else if(cbHandCardCount<=5)
            {
                BYTE cbMinLogicCard = GetCardLogicValue(0x4F)+1 ;
                BYTE cbCanOutIndex = 0 ;
                for(BYTE i=0; i<4; ++i)
                    if(cbMinSingleCardCount[i]<MAX_COUNT && cbMinSingleCardCount[i]<=cbMinSingleCountInFour && cbMinLogicCard>GetCardLogicValue(CanOutCard.cbCardData[cbIndex[i]][0]) &&
                       GetCardLogicValue(CanOutCard.cbCardData[cbIndex[i]][0])<=14)
                    {
                        cbMinLogicCard = GetCardLogicValue(CanOutCard.cbCardData[cbIndex[i]][0]) ;
                        cbCanOutIndex = cbIndex[i] ;
                    }
                
                if(cbMinLogicCard != (GetCardLogicValue(0x4F)+1))
                {
                    OutCardResult.cbCardCount=CanOutCard.cbEachHandCardCount[cbCanOutIndex];
                    CopyMemory(OutCardResult.cbResultCard,CanOutCard.cbCardData[cbCanOutIndex],CanOutCard.cbEachHandCardCount[cbCanOutIndex]*sizeof(BYTE));
                    
                    return ;
                }
            }
            
            return ;
        }
        else
        {
            return ;
        }
        
    }
    else
    {
        if(CanOutCard.cbCardTypeCount>0)
        {
            BYTE cbMinLogicCardValue = GetCardLogicValue(0x4F)+1 ;
            bool bFindCard = false ;
            BYTE cbCanOutIndex=0 ;
            for(BYTE i=0; i<4; ++i)
            {
                BYTE Index = cbIndex[i] ;
                
                if((cbMinSingleCardCount[i]<cbOriginSingleCardCount+4)  &&  (cbMinSingleCardCount[i]<=cbMinSingleCountInFour || cbMinSingleCardCount[i]<=cbMinSingleCountInFour+1 &&
                                                                             CanOutCard.cbCardType >= CT_THREE_LINE_TAKE_ONE && CanOutCard.cbCardType <= CT_THREE_LINE_TAKE_TWO ) &&
                   cbMinLogicCardValue>GetCardLogicValue(CanOutCard.cbCardData[Index][0]))
                {
                    bool bNoLargeCard = true ;
                    
                    if(m_cbUserCardCount[m_wBankerUser]>=4 && cbHandCardCount>=5  && CanOutCard.cbEachHandCardCount[Index]>=2 &&
                       GetCardLogicValue(CanOutCard.cbCardData[Index][0])>=15 &&
                       GetCardLogicValue(cbTurnCardData[0])<13 &&
                       GetCardLogicValue(cbTurnCardData[0])<GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0]) &&
                       CanOutCard.cbEachHandCardCount[Index]!=cbHandCardCount)
                        bNoLargeCard=false ;
                    
                    for(BYTE k=3; k<CanOutCard.cbEachHandCardCount[Index]; ++k)
                    {
                        if(GetCardLogicValue(CanOutCard.cbCardData[Index][k])>=15 &&
                           CanOutCard.cbEachHandCardCount[Index]!=cbHandCardCount)
                            bNoLargeCard = false ;
                    }
                    if(bNoLargeCard)
                    {
                        bFindCard = true ;
                        cbCanOutIndex = Index ;
                        cbMinLogicCardValue = GetCardLogicValue(CanOutCard.cbCardData[Index][0]) ;
                    }
                }
            }
            
            if(bFindCard)
            {
                BYTE cbLargestLogicCard = GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0]) ;
                bool bCanOut=true ;
                
                if(GetCardLogicValue(cbTurnCardData[0])<cbLargestLogicCard)
                {
                    if(GetCardColor(CanOutCard.cbCardData[cbCanOutIndex][0])==0x40 && GetCardLogicValue(cbTurnCardData[0])<=14 && cbHandCardCount>5)
                    {
                        bCanOut = false ;
                    }
                }
                if(GetCardLogicValue(CanOutCard.cbCardData[cbCanOutIndex][0])>=16 && cbHandCardCount>=2 && cbHandCardData[0]==0x4F && cbHandCardData[1]==0x4E)
                {
                    bool bOutMissileCard = false ;
                    BYTE cbRemainCardData[20], cbRemainCardCount=cbHandCardCount ;
                    CopyMemory(cbRemainCardData, cbHandCardData, cbHandCardCount) ;
                    RemoveCard(cbRemainCardData, 2, cbRemainCardData, cbRemainCardCount) ;
                    cbRemainCardCount -= 2 ;
                    if(CT_ERROR!=GetCardType(cbRemainCardData, cbRemainCardCount)) bOutMissileCard = true;
                    
                    BYTE cbRemainLargestCard = GetCardLogicValue(cbRemainCardData[0]) ;
                    if(cbRemainCardCount<5 && cbRemainCardCount>0 && GetCardLogicValue(cbRemainCardData[0])>=14) bOutMissileCard = true;
                    
                    BYTE cbSingleCardCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, CanOutCard.cbCardData[cbCanOutIndex],
                                                                   CanOutCard.cbEachHandCardCount[cbCanOutIndex]) ;
                    if(cbSingleCardCount<=1 && GetCardLogicValue(cbRemainCardData[0])>=11) bOutMissileCard = true;
                    
                    if (GetCardLogicValue(cbRemainCardData[0]) <= 10 && CT_ERROR == GetCardType(cbRemainCardData, cbRemainCardCount) &&
                        GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0]) > 10)
                        bOutMissileCard = false ;
                    
                    if(bOutMissileCard)
                    {
                        BYTE cbIndex = CardTypeResult[CT_BOMB_CARD].cbCardTypeCount - 1 ;
                        
                        OutCardResult.cbCardCount = CardTypeResult[CT_BOMB_CARD].cbEachHandCardCount[cbIndex] ;
                        CopyMemory(OutCardResult.cbResultCard, CardTypeResult[CT_BOMB_CARD].cbCardData[cbIndex], OutCardResult.cbCardCount) ;
                        return ;
                    }
                }
                
                if(bCanOut)
                {
                    OutCardResult.cbCardCount=CanOutCard.cbEachHandCardCount[cbCanOutIndex];
                    CopyMemory(OutCardResult.cbResultCard,CanOutCard.cbCardData[cbCanOutIndex],CanOutCard.cbEachHandCardCount[cbCanOutIndex]*sizeof(BYTE));
                    
                    return ;
                }
            }
            
            if(cbOutCardType==CT_SINGLE)
            {
                BYTE cbLargestLogicCard = GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0]) ;
                
                if(GetCardLogicValue(cbTurnCardData[0])==14 ||
                   GetCardLogicValue(cbTurnCardData[0])>=cbLargestLogicCard ||
                   (GetCardLogicValue(cbTurnCardData[0])<cbLargestLogicCard-1) ||
                   m_cbUserCardCount[m_wBankerUser]<=5)
                {
                    BYTE cbIndex=MAX_COUNT ;
                    for(BYTE i=0; i<cbHandCardCount; ++i)
                        if(GetCardLogicValue(cbHandCardData[i])>GetCardLogicValue(cbTurnCardData[0]) &&	GetCardLogicValue(cbHandCardData[i])>=15)
                        {
                            cbIndex = i ;
                        }
                    if(cbIndex!=MAX_COUNT)
                    {
                        OutCardResult.cbCardCount=1;
                        OutCardResult.cbResultCard[0] = cbHandCardData[cbIndex] ;
                        
                        return ;
                    }
                }
            }
        }
        
        if(CardTypeResult[CT_BOMB_CARD].cbCardTypeCount>0 ||
           (NORMAL_COUNT  == cbHandCardCount&& NORMAL_COUNT == m_cbUserCardCount[(m_wBankerUser+1)%GAME_PLAYER]))
        {
            tagOutCardTypeResult const &BomCard = CardTypeResult[CT_BOMB_CARD] ;
            BYTE cbMinLogicValue = GetCardLogicValue(BomCard.cbCardData[0][0]) ;
            BYTE Index = 0 ;
            for(BYTE i=0; i<BomCard.cbCardTypeCount; ++i)
            {
                if(cbMinLogicValue>GetCardLogicValue(BomCard.cbCardData[i][0]))
                {
                    cbMinLogicValue = GetCardLogicValue(BomCard.cbCardData[i][0]) ;
                    Index = i ;
                }
            }
            
            bool bOutBomb = false ;
            
            if (NORMAL_COUNT  == cbHandCardCount && NORMAL_COUNT == m_cbUserCardCount[(m_wBankerUser+1)%GAME_PLAYER] && CT_ERROR != GetCardType(m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser]))
                bOutBomb = true ;
            
            BYTE cbRemainCardData[20], cbRemainCardCount=cbHandCardCount ;
            CopyMemory(cbRemainCardData, cbHandCardData, cbHandCardCount) ;
            RemoveCard(BomCard.cbCardData[Index], BomCard.cbEachHandCardCount[Index], cbRemainCardData, cbRemainCardCount) ;
            cbRemainCardCount -= BomCard.cbEachHandCardCount[Index] ;
            if(CT_ERROR!=GetCardType(cbRemainCardData, cbRemainCardCount)) bOutBomb = true ;
            
            BYTE cbSingleCardCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, BomCard.cbCardData[Index],BomCard.cbEachHandCardCount[Index]) ;
            if(cbSingleCardCount==0 && GetCardLogicValue(cbRemainCardData[0]) > GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0]))
                bOutBomb = true ;
            
            BYTE cbRemainCardType = GetCardType(m_cbAllCardData[wOutCardUser], m_cbUserCardCount[wOutCardUser]) ;
            if(cbRemainCardType>CT_ERROR && cbRemainCardType<CT_FOUR_LINE_TAKE_ONE && GetCardLogicValue(m_cbAllCardData[wOutCardUser][0])<15 &&
               cbSingleCardCount < 2 && (GetCardLogicValue(cbRemainCardData[0]) >= GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0])))
                bOutBomb = true ;
            
            BYTE cbRemainLargestCard = GetCardLogicValue(cbRemainCardData[0]) ;
            if(cbRemainCardCount<5 && cbRemainCardCount>0 && (cbRemainLargestCard!=GetCardLogicValue(BomCard.cbCardData[Index][0])) &&
               cbRemainLargestCard>GetCardLogicValue(m_cbAllCardData[wOutCardUser][0]) && cbRemainLargestCard > 14) bOutBomb = true ;
            
            tagAnalyseResultA AnalyseResult ;
            AnalysebCardDataA(cbRemainCardData, cbRemainCardCount, AnalyseResult) ;
            
            if (m_cbUserCardCount[m_wBankerUser] ==1 &&  (AnalyseResult.bDoubleCount * 2 + AnalyseResult.bThreeCount * 3 + AnalyseResult.bFourCount * 4 + 1 >= cbRemainCardCount)) bOutBomb = true ;
            
            if(bOutBomb)
            {
                OutCardResult.cbCardCount=BomCard.cbEachHandCardCount[Index];
                CopyMemory(OutCardResult.cbResultCard,BomCard.cbCardData[Index],BomCard.cbEachHandCardCount[Index]*sizeof(BYTE));
            }
            
            return ;
        }
        
        return ;
    }
    return ;
}

void DDZCGameLogicSingle::UndersideOfBankerOutCard(const BYTE cbHandCardData[], BYTE cbHandCardCount, WORD wMeChairID,tagOutCardResult & OutCardResult)
{
	tagOutCardTypeResult CardTypeResult[12+1] ;
	ZeroMemory(CardTypeResult, sizeof(CardTypeResult)) ;
    
	ZeroMemory(&OutCardResult, sizeof(OutCardResult)) ;
    
	BYTE cbLineCard[MAX_COUNT] ;
	BYTE cbThreeLineCard[MAX_COUNT] ;
	BYTE cbDoubleLineCard[MAX_COUNT] ;
	BYTE cbLineCardCount;
	BYTE cbThreeLineCardCount ;
	BYTE cbDoubleLineCount ;
	GetAllLineCard(cbHandCardData, cbHandCardCount, cbLineCard, cbLineCardCount) ;
	GetAllThreeCard(cbHandCardData, cbHandCardCount, cbThreeLineCard, cbThreeLineCardCount) ;
	GetAllDoubleCard(cbHandCardData, cbHandCardCount, cbDoubleLineCard, cbDoubleLineCount) ;
    
	BYTE cbSingleCardCount = MAX_COUNT+CT_MISSILE_CARD ;
	bool bFindBestCard = false ;
	AnalyseOutCardType(cbHandCardData, cbHandCardCount, CardTypeResult) ;
	for(BYTE cbCardType=CT_SINGLE; cbCardType<=CT_MISSILE_CARD; ++cbCardType)
		if(CardTypeResult[cbCardType].cbCardTypeCount>0)
		{
			for(long lIndex=0; lIndex<CardTypeResult[cbCardType].cbCardTypeCount; ++lIndex)
			{
				WORD wMeChairID = (m_wBankerUser+1)%GAME_PLAYER ;
                
				if(TestOutAllCard(wMeChairID, CardTypeResult[cbCardType].cbCardData[lIndex], CardTypeResult[cbCardType].cbEachHandCardCount[lIndex], true))
				{
					BYTE cbTmpSingleCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, CardTypeResult[cbCardType].cbCardData[lIndex],
                                                                  CardTypeResult[cbCardType].cbEachHandCardCount[lIndex]) ;
                    
					if (cbTmpSingleCount >= MAX_COUNT) continue ;
                    
					BYTE cbBombCardType = GetCardType(CardTypeResult[cbCardType].cbCardData[lIndex], CardTypeResult[cbCardType].cbEachHandCardCount[lIndex]) ;
					if (cbBombCardType == CT_BOMB_CARD) cbTmpSingleCount += 4 ;
					else if (cbBombCardType == CT_MISSILE_CARD) cbTmpSingleCount += 5 ;
					else if ( 15 == GetCardLogicValue( CardTypeResult[ cbCardType ].cbCardData[ lIndex ][ 0 ] ) ) cbTmpSingleCount += 2;
					else if ( 15 < GetCardLogicValue( CardTypeResult[ cbCardType ].cbCardData[ lIndex ][ 0 ] ) ) cbTmpSingleCount += 3;
                    
                    
                    
					if(cbTmpSingleCount <= cbSingleCardCount)
					{
						OutCardResult.cbCardCount=CardTypeResult[cbCardType].cbEachHandCardCount[lIndex];
						CopyMemory(OutCardResult.cbResultCard, CardTypeResult[cbCardType].cbCardData[lIndex],
                                   CardTypeResult[cbCardType].cbEachHandCardCount[lIndex]*sizeof(BYTE));
						cbSingleCardCount = cbTmpSingleCount ;
                        
						bFindBestCard = true ;
						for (int k=0;k<OutCardResult.cbCardCount;k++)
						{
							printf("OutCardResult.cbResultCard[%d]=%d  ",k,OutCardResult.cbResultCard);
						}
                        
						printf("\n￉￨ￖￃﾱ￤￁﾿\n");
					}
				}
			}
		}
    if (bFindBestCard) return ;
    
    if ( cbHandCardCount == 4 && GetCardLogicValue(cbHandCardData[1]) == 16 && m_cbUserCardCount[m_wBankerUser] == 1 &&
        GetCardLogicValue(cbHandCardData[2]) < GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0]))
    {
        OutCardResult.cbCardCount = 1 ;
        OutCardResult.cbResultCard[0] = cbHandCardData[2] ;
        return ;
    }
    
    if ( AnalyseFourCardType(cbHandCardData, cbHandCardCount, m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser], OutCardResult ) )
    {
        return ;
    }
    
    
    {
        if(cbLineCardCount+1==cbHandCardCount && CT_SINGLE==GetCardType(cbLineCard, cbLineCardCount))
        {
            OutCardResult.cbCardCount = cbLineCardCount ;
            CopyMemory(OutCardResult.cbResultCard, cbLineCard, cbLineCardCount) ;
        }
        else if(cbThreeLineCardCount+1==cbHandCardCount && CT_THREE_LINE==GetCardType(cbThreeLineCard, cbThreeLineCardCount))
        {
            OutCardResult.cbCardCount = cbThreeLineCardCount ;
            CopyMemory(OutCardResult.cbResultCard, cbThreeLineCard, cbThreeLineCardCount) ;
        }
        else if(cbDoubleLineCount+1==cbHandCardCount && CT_DOUBLE_LINE==GetCardType(cbDoubleLineCard, cbDoubleLineCount))
        {
            OutCardResult.cbCardCount = cbDoubleLineCount ;
            CopyMemory(OutCardResult.cbResultCard, cbDoubleLineCard, cbDoubleLineCount) ;
        }
        else if(cbHandCardCount>2 && cbHandCardData[0]==0x4F && cbHandCardData[1]==0x4E && CT_ERROR!=GetCardType(cbHandCardData+2, cbHandCardCount-2) &&
				CT_FOUR_LINE_TAKE_ONE != GetCardType(cbHandCardData+2, cbHandCardCount-2) && CT_FOUR_LINE_TAKE_TWO != GetCardType(cbHandCardData+2, cbHandCardCount-2))
        {
            OutCardResult.cbCardCount = 2 ;
            OutCardResult.cbResultCard[0] = 0x4F ;
            OutCardResult.cbResultCard[1] = 0x4E ;
        }
        
        if(OutCardResult.cbCardCount>0)
        {
            return ;
        }
    }
    if(cbHandCardCount==3 && GetCardColor(cbHandCardData[0])==0x40 && GetCardColor(cbHandCardData[1])==0x40)
    {
        OutCardResult.cbCardCount = 2 ;
        OutCardResult.cbResultCard[0] = 0x4F ;
        OutCardResult.cbResultCard[1] = 0x4E ;
        return ;
    }
    else if(cbHandCardCount==2 && GetCardColor(cbHandCardData[0])==0x40 && GetCardColor(cbHandCardData[1])==0x40)
    {
        OutCardResult.cbCardCount = 2 ;
        OutCardResult.cbResultCard[0] = 0x4F ;
        OutCardResult.cbResultCard[1] = 0x4E ;
        return ;
    }
    else if(CT_ERROR!=GetCardType(cbHandCardData, cbHandCardCount) && CT_FOUR_LINE_TAKE_ONE!=GetCardType(cbHandCardData, cbHandCardCount) && CT_FOUR_LINE_TAKE_TWO!=GetCardType(cbHandCardData, cbHandCardCount))
    {
        OutCardResult.cbCardCount = cbHandCardCount ;
        CopyMemory(OutCardResult.cbResultCard, cbHandCardData, cbHandCardCount) ;
        return ;
    }
    
    if(cbHandCardCount>=2)
    {
        tagOutCardTypeResult BankerCanOutCardType1[13] ;
        ZeroMemory(BankerCanOutCardType1, sizeof(BankerCanOutCardType1)) ;
        tagOutCardTypeResult BankerCanOutCardType2[13] ;
        ZeroMemory(BankerCanOutCardType2, sizeof(BankerCanOutCardType2)) ;
        
        BYTE cbFirstHandCardType = GetCardType(cbHandCardData, cbHandCardCount-1) ;
        BYTE cbSecondHandCardType = GetCardType(cbHandCardData+1, cbHandCardCount-1) ;
        
        BYTE cbAllBombCardData[MAX_COUNT], cbAllBombCount=0 ;
        GetAllBomCard(cbHandCardData, cbHandCardCount, cbAllBombCardData, cbAllBombCount) ;
        
        if (cbAllBombCount <= 0 && cbFirstHandCardType!=CT_THREE_LINE_TAKE_ONE && cbFirstHandCardType!=CT_THREE_LINE_TAKE_TWO)
        {
            if(cbFirstHandCardType!=CT_ERROR)
                AnalyseOutCardType(m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser], cbHandCardData, cbHandCardCount-1, BankerCanOutCardType1) ;
            if(cbSecondHandCardType!=CT_ERROR)
                AnalyseOutCardType(m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser], cbHandCardData+1, cbHandCardCount-1, BankerCanOutCardType2) ;
            
            if(cbSecondHandCardType!=CT_ERROR && cbSecondHandCardType!=CT_FOUR_LINE_TAKE_ONE && cbSecondHandCardType!= CT_FOUR_LINE_TAKE_TWO &&
               BankerCanOutCardType2[cbSecondHandCardType].cbCardTypeCount==0 && BankerCanOutCardType2[CT_BOMB_CARD].cbCardTypeCount==0)
            {
                OutCardResult.cbCardCount = cbHandCardCount-1 ;
                CopyMemory(OutCardResult.cbResultCard, cbHandCardData+1, cbHandCardCount-1) ;
                return ;
            }
            
            if(cbFirstHandCardType!=CT_ERROR && cbFirstHandCardType!=CT_FOUR_LINE_TAKE_ONE && cbFirstHandCardType!= CT_FOUR_LINE_TAKE_TWO &&
               BankerCanOutCardType1[cbFirstHandCardType].cbCardTypeCount==0 && BankerCanOutCardType2[CT_BOMB_CARD].cbCardTypeCount==0)
            {
                OutCardResult.cbCardCount = cbHandCardCount-1 ;
                CopyMemory(OutCardResult.cbResultCard, cbHandCardData, cbHandCardCount-1) ;
                return ;
            }
            
            if(GetCardLogicValue(cbHandCardData[0])>=GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0]) &&
               CT_ERROR!=cbSecondHandCardType && cbSecondHandCardType!=CT_FOUR_LINE_TAKE_ONE && cbSecondHandCardType!= CT_FOUR_LINE_TAKE_TWO &&
               BankerCanOutCardType2[CT_BOMB_CARD].cbCardTypeCount==0)
            {
                OutCardResult.cbCardCount = 1 ;
                OutCardResult.cbResultCard[0] = cbHandCardData[0] ;
                return ;
            }
            
            if(CT_ERROR!=cbSecondHandCardType && cbSecondHandCardType!=CT_FOUR_LINE_TAKE_ONE && cbSecondHandCardType!= CT_FOUR_LINE_TAKE_TWO &&
               BankerCanOutCardType2[CT_BOMB_CARD].cbCardTypeCount==0)
            {
                OutCardResult.cbCardCount = cbHandCardCount-1 ;
                CopyMemory(OutCardResult.cbResultCard, cbHandCardData+1, cbHandCardCount-1) ;
                return ;
            }
        }
        else
        {
            BYTE cbRemainCard[MAX_COUNT], cbRemainCount=0 ;
            CopyMemory(cbRemainCard, cbHandCardData, cbHandCardCount) ;
            cbRemainCount = cbHandCardCount ;
            RemoveCard(cbAllBombCardData, cbAllBombCount, cbRemainCard, cbRemainCount) ;
            cbRemainCount -= cbAllBombCount ;
            if (GetCardType(cbRemainCard, cbRemainCount) != CT_ERROR)
            {
                OutCardResult.cbCardCount = cbRemainCount ;
                CopyMemory(OutCardResult.cbResultCard, cbRemainCard, cbRemainCount) ;
                return ;
            }
        }
    }
    
    WORD wFriendID = (m_wBankerUser+2)%GAME_PLAYER ;
    BYTE cbFriendCardType = GetCardType(m_cbAllCardData[wFriendID], m_cbUserCardCount[wFriendID]) ;
    
    if(CT_SINGLE==cbFriendCardType)
    {
        if(m_cbUserCardCount[wFriendID]==1 && GetCardLogicValue(cbHandCardData[cbHandCardCount-1]) < GetCardLogicValue(m_cbAllCardData[wFriendID][0]))
        {
            OutCardResult.cbCardCount = 1 ;
            OutCardResult.cbResultCard[0] = cbHandCardData[cbHandCardCount-1] ;
            return ;
        }
    }
    else if(CT_DOUBLE==cbFriendCardType && cbDoubleLineCount>=2)
    {
        if(GetCardLogicValue(cbDoubleLineCard[cbDoubleLineCount-1]) < GetCardLogicValue(m_cbAllCardData[wFriendID][0]))
        {
            OutCardResult.cbCardCount = 2 ;
            OutCardResult.cbResultCard[0] = cbDoubleLineCard[cbDoubleLineCount-2] ;
            OutCardResult.cbResultCard[1] = cbDoubleLineCard[cbDoubleLineCount-1] ;
            
            return ;
        }
    }
    if (1 == m_cbUserCardCount[m_wBankerUser] && cbHandCardCount >= 2 && m_cbUserCardCount[wFriendID] >= 2)
    {
        tagAnalyseResultA MeAnalyseResult ;
        ZeroMemory(&MeAnalyseResult, sizeof(MeAnalyseResult)) ;
        
        AnalysebCardDataA(cbHandCardData, cbHandCardCount, MeAnalyseResult) ;
        
        tagAnalyseResultA FriendAnalyseResult ;
        ZeroMemory(&FriendAnalyseResult, sizeof(FriendAnalyseResult)) ;
        
        AnalysebCardDataA(m_cbAllCardData[wFriendID], m_cbUserCardCount[wFriendID], FriendAnalyseResult) ;
        
        if ((m_cbUserCardCount[wFriendID] == (FriendAnalyseResult.bDoubleCount * 2 + FriendAnalyseResult.bThreeCount * 3 + FriendAnalyseResult.bFourCount * 4) ||
             m_cbUserCardCount[wFriendID] == (FriendAnalyseResult.bDoubleCount * 2 + FriendAnalyseResult.bThreeCount * 3 + FriendAnalyseResult.bFourCount * 4 + 1)) &&
            MeAnalyseResult.bDoubleCount > 0 && FriendAnalyseResult.bDoubleCount > 0)
        {
            
            BYTE cbMeLeastDoubleCardLogic = GetCardLogicValue(MeAnalyseResult.m_bDCardData[MeAnalyseResult.bDoubleCount*2-2]) ;
            
            BYTE cbFriendLargestDoublecardLogic = GetCardLogicValue(FriendAnalyseResult.m_bDCardData[0]) ;
            
            if (cbMeLeastDoubleCardLogic < 14 && cbMeLeastDoubleCardLogic < cbFriendLargestDoublecardLogic)
            {
                OutCardResult.cbCardCount = 2 ;
                OutCardResult.cbResultCard[0] = MeAnalyseResult.m_bDCardData[MeAnalyseResult.bDoubleCount*2-2] ;
                OutCardResult.cbResultCard[1] = MeAnalyseResult.m_bDCardData[MeAnalyseResult.bDoubleCount*2-1] ;
                return ;
            }
            
        }
    }
    
    //	if(m_cbUserCardCount[m_wBankerUser]<=5)
    {
        tagOutCardTypeResult MeOutCardTypeResult[13] ;
        ZeroMemory(MeOutCardTypeResult, sizeof(MeOutCardTypeResult)) ;
        AnalyseOutCardType(cbHandCardData, cbHandCardCount, MeOutCardTypeResult) ;
        
        WORD wFriendID ;
        for(WORD wChairID=0; wChairID<GAME_PLAYER; ++wChairID)
            if(wChairID!=m_wBankerUser && wMeChairID!=wChairID) wFriendID = wChairID ;
        
        BYTE cbMinSingleCardCount[4] ;
        cbMinSingleCardCount[0]=MAX_COUNT ;
        cbMinSingleCardCount[1]=MAX_COUNT ;
        cbMinSingleCardCount[2]=MAX_COUNT ;
        cbMinSingleCardCount[3]=MAX_COUNT ;
        BYTE cbIndex[4]={0} ;
        BYTE cbOutcardType[4]={CT_ERROR} ;
        BYTE cbMinValue=MAX_COUNT ;
        BYTE cbMinSingleCountInFour=MAX_COUNT ;
        BYTE cbMinCardType=CT_ERROR ;
        BYTE cbMinIndex=0 ;
        
        for(BYTE cbCardType=CT_DOUBLE; cbCardType<CT_BOMB_CARD; ++cbCardType)
        {
            tagOutCardTypeResult const &tmpCardResult = MeOutCardTypeResult[cbCardType] ;
            
            BYTE cbThisHandCardCount = MAX_COUNT ;
            
            tagOutCardTypeResult BankerCanOutCard[13] ;
            ZeroMemory(BankerCanOutCard, sizeof(BankerCanOutCard)) ;
            
            tagOutCardTypeResult FriendOutCardTypeResult[13] ;
            ZeroMemory(FriendOutCardTypeResult, sizeof(FriendOutCardTypeResult)) ;
            
            for(BYTE i=0; i<tmpCardResult.cbCardTypeCount; ++i)
            {
                if ( cbCardType == CT_DOUBLE )
                {
                    tagAnalyseResultA AnalyseResult ;
                    ZeroMemory( &AnalyseResult,  sizeof( AnalyseResult ) ) ;
                    AnalysebCardDataA( cbHandCardData, cbHandCardCount, AnalyseResult ) ;
                    if ( AnalyseResult.bSignedCount + AnalyseResult.bThreeCount * 3 == cbHandCardCount )
                    {
                        bool bContinue = false ;
                        for ( BYTE cbThreeIndex = 0; cbThreeIndex < AnalyseResult.bThreeCount; ++cbThreeIndex )
                            if ( GetCardValue(  tmpCardResult.cbCardData[i][0] ) == GetCardValue( AnalyseResult.m_bTCardData[3 * cbThreeIndex] ) )
                            {
                                bContinue = true ;
                                break ;
                            }
                        if ( bContinue ) continue ;
                    }
                }
                
                BYTE cbTmpCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, tmpCardResult.cbCardData[i], tmpCardResult.cbEachHandCardCount[i]) ;
                
                if(tmpCardResult.cbEachHandCardCount[i]!=cbThisHandCardCount)
                {
                    cbThisHandCardCount = tmpCardResult.cbEachHandCardCount[i] ;
                    AnalyseOutCardType(m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser],
                                       tmpCardResult.cbCardData[i], tmpCardResult.cbEachHandCardCount[i] ,BankerCanOutCard) ;
                    AnalyseOutCardType(m_cbAllCardData[wFriendID], m_cbUserCardCount[wFriendID],
                                       tmpCardResult.cbCardData[i], tmpCardResult.cbEachHandCardCount[i] ,FriendOutCardTypeResult) ;
                }
                
                BYTE cbMaxValue=0 ;
                BYTE Index = 0 ;
                
                
                BYTE cbCurrentCardType = GetCardType(tmpCardResult.cbCardData[i], cbThisHandCardCount) ;
                if (cbThisHandCardCount != cbHandCardCount && cbCurrentCardType >= CT_SINGLE_LINE && cbCurrentCardType <= CT_THREE_LINE_TAKE_TWO &&
                    ( GetCardLogicValue(tmpCardResult.cbCardData[i][cbThisHandCardCount-1]) > GetCardLogicValue(cbHandCardData[cbHandCardCount-2]) ||
                     GetCardLogicValue(tmpCardResult.cbCardData[i][0]) >= 11 ))
                {
                    BYTE cbRemainCardData[MAX_COUNT], cbRemainCardCount ;
                    CopyMemory(cbRemainCardData, cbHandCardData, cbHandCardCount) ;
                    cbRemainCardCount = cbHandCardCount ;
                    
                    RemoveCard(tmpCardResult.cbCardData[i], cbThisHandCardCount, cbRemainCardData, cbRemainCardCount) ;
                    cbRemainCardCount -= cbThisHandCardCount ;
                    
                    BYTE cbCurrentLargestLogicCard = GetCardLogicValue(tmpCardResult.cbCardData[i][0]) ;
                    
                    if (GetCardType(cbRemainCardData, cbRemainCardCount) == CT_ERROR && (cbCurrentCardType >= CT_THREE_LINE_TAKE_ONE &&
                                                                                         cbCurrentCardType <= CT_THREE_LINE_TAKE_TWO && cbCurrentLargestLogicCard >= 11 && cbThisHandCardCount <=5 ||
                                                                                         cbCurrentCardType == CT_SINGLE_LINE && cbThisHandCardCount <= 6 && cbCurrentLargestLogicCard >= 12 ||
                                                                                         cbCurrentCardType >= CT_DOUBLE_LINE && cbCurrentCardType <= CT_THREE_LINE && cbCurrentLargestLogicCard >= 12 && cbThisHandCardCount <= 8))
                    {
                        
                        if ( cbCurrentCardType >= CT_SINGLE_LINE && cbCurrentCardType <= CT_THREE_LINE &&
                            GetCardLogicValue(tmpCardResult.cbCardData[i][cbThisHandCardCount - 1]) > GetCardLogicValue(cbHandCardData[cbHandCardCount-3]) )
                            continue ;
                        
                        if ( cbCurrentCardType >= CT_THREE_LINE_TAKE_ONE && cbCurrentCardType <= CT_THREE_LINE_TAKE_TWO &&
                            GetCardLogicValue(tmpCardResult.cbCardData[i][0]) > GetCardLogicValue(cbHandCardData[cbHandCardCount-3]) )
                            continue ;
                    }
                }
                
                if (cbCardType == CT_DOUBLE && GetCardLogicValue(tmpCardResult.cbCardData[i][0]) >= 11)
                {
                    BYTE cbAllSingleCardData[MAX_COUNT], cbAllSingleCount ;
                    cbAllSingleCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, NULL, 0, cbAllSingleCardData) ;
                    if (cbAllSingleCount >= 2 && GetCardLogicValue(cbAllSingleCardData[cbAllSingleCount-2]) < 10) continue ;
                }
                
                if((BankerCanOutCard[cbCardType].cbCardTypeCount>0&&FriendOutCardTypeResult[cbCardType].cbCardTypeCount==0) || (BankerCanOutCard[cbCardType].cbCardTypeCount>0 && FriendOutCardTypeResult[cbCardType].cbCardTypeCount>0 &&
                                                                                                                                GetCardLogicValue(FriendOutCardTypeResult[cbCardType].cbCardData[0][0])<=GetCardLogicValue(BankerCanOutCard[cbCardType].cbCardData[0][0])))
                {
                    
                    if( BankerCanOutCard[cbCardType].cbEachHandCardCount[0] > 0 && m_cbUserCardCount[m_wBankerUser]<=BankerCanOutCard[cbCardType].cbEachHandCardCount[0]+1)
                        continue ;
                    
                }
                if(tmpCardResult.cbEachHandCardCount[i] != cbHandCardCount)
                {
                    bool bHaveLargeCard=false ;
                    for(BYTE j=0; j<tmpCardResult.cbEachHandCardCount[i]; ++j)
                        if(GetCardLogicValue(tmpCardResult.cbCardData[i][j])>=15) bHaveLargeCard=true ;
                    
                    if(cbCardType!=CT_SINGLE_LINE && cbCardType!=CT_DOUBLE_LINE && GetCardLogicValue(tmpCardResult.cbCardData[i][0])==14) bHaveLargeCard=true ;
                    
                    if(bHaveLargeCard) continue ;
                }
                
                if(tmpCardResult.cbEachHandCardCount[i]==m_cbUserCardCount[m_wBankerUser] && cbCardType==GetCardType(m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser]) &&
                   GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0])>GetCardLogicValue(tmpCardResult.cbCardData[i][0])) continue ;
                
                for(BYTE j=0; j<4; ++j)
                {
                    if(cbMinSingleCardCount[j]>=cbTmpCount)
                    {
                        cbMinSingleCardCount[j] = cbTmpCount ;
                        cbIndex[j] = i ;
                        cbOutcardType[j] = cbCardType ;
                        break ;
                    }
                }
                
                if(cbMinSingleCountInFour>=cbTmpCount)
                {
                    cbMinCardType = cbCardType ;
                    cbMinSingleCountInFour=cbTmpCount ;
                    cbMinIndex=i ;
                }
            }
        }
        
        if(cbMinSingleCountInFour>=AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, NULL, 0)+3 &&
           m_cbUserCardCount[m_wBankerUser]>4)
            cbMinSingleCountInFour=MAX_COUNT ;
        
        if(cbMinSingleCountInFour!=MAX_COUNT)
        {
            BYTE Index = cbMinIndex ;
            
            for(BYTE i=0; i<4; ++i)
            {
                printf("ﾳ￶ￅￆ1");
                if(cbOutcardType[i]==cbMinCardType && cbMinSingleCardCount[i]<=cbMinSingleCountInFour &&
                   GetCardLogicValue(MeOutCardTypeResult[cbMinCardType].cbCardData[cbIndex[i]][0])<GetCardLogicValue(MeOutCardTypeResult[cbMinCardType].cbCardData[Index][0]))
                    Index = cbIndex[i] ;
            }
            
            if(cbHandCardCount==3 && GetCardColor(cbHandCardData[0])==0x40 && GetCardColor(cbHandCardData[1])==0x40)
            {
                OutCardResult.cbCardCount = 2 ;
                OutCardResult.cbResultCard[0] = 0x4F ;
                OutCardResult.cbResultCard[1] = 0x4E ;
                return ;
            }
            else if(cbHandCardCount==2 && GetCardColor(cbHandCardData[0])==0x40 && GetCardColor(cbHandCardData[1])==0x40)
            {
                OutCardResult.cbCardCount = 2 ;
                OutCardResult.cbResultCard[0] = 0x4F ;
                OutCardResult.cbResultCard[1] = 0x4E ;
                return ;
            }
            else
            {
                printf("ﾳ￶ￅￆ2");
                OutCardResult.cbCardCount=MeOutCardTypeResult[cbMinCardType].cbEachHandCardCount[Index];
                CopyMemory(OutCardResult.cbResultCard,MeOutCardTypeResult[cbMinCardType].cbCardData[Index],MeOutCardTypeResult[cbMinCardType].cbEachHandCardCount[Index]*sizeof(BYTE));
                return ;
            }
            return ;
        }
        
        if(OutCardResult.cbCardCount<=0 && m_cbUserCardCount[m_wBankerUser]<=5)
        {
            if(m_cbUserCardCount[m_wBankerUser]==1 && MeOutCardTypeResult[CT_SINGLE].cbCardTypeCount>0)
            {
                BYTE Index=MAX_COUNT ;
                for(BYTE i=0; i<MeOutCardTypeResult[CT_SINGLE].cbCardTypeCount; ++i)
                {
                    if(GetCardLogicValue(MeOutCardTypeResult[CT_SINGLE].cbCardData[i][0])>=GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0]))
                    {
                        Index=i ;
                    }
                    else break ;
                }
                
                if(MAX_COUNT!=Index)
                {
                    printf("ﾳ￶ￅￆ3");
                    OutCardResult.cbCardCount = MeOutCardTypeResult[CT_SINGLE].cbEachHandCardCount[Index] ;
                    CopyMemory(OutCardResult.cbResultCard, MeOutCardTypeResult[CT_SINGLE].cbCardData[Index], OutCardResult.cbCardCount) ;
                    return ;
                }
            }
        }
    }
    
    BYTE cbFirstCard=0 ;
    for(BYTE i=0; i<cbHandCardCount; ++i)
        if(GetCardLogicValue(cbHandCardData[i])<15)
        {
            cbFirstCard = i ;
            break ;
        }
    
    if(cbFirstCard<cbHandCardCount-1)
        AnalyseOutCardType(cbHandCardData+cbFirstCard, cbHandCardCount-cbFirstCard, CardTypeResult) ;
    else
        AnalyseOutCardType(cbHandCardData, cbHandCardCount, CardTypeResult) ;
    
    BYTE cbMinSingleCardCount[4] ;
    cbMinSingleCardCount[0]=MAX_COUNT ;
    cbMinSingleCardCount[1]=MAX_COUNT ;
    cbMinSingleCardCount[2]=MAX_COUNT ;
    cbMinSingleCardCount[3]=MAX_COUNT ;
    BYTE cbIndex[4]={0} ;
    BYTE cbOutcardType[4]={CT_ERROR} ;
    BYTE cbMinValue=MAX_COUNT ;
    BYTE cbMinSingleCountInFour=MAX_COUNT ;
    BYTE cbMinCardType=CT_ERROR ;
    BYTE cbMinIndex=0 ;
    
    for(BYTE cbCardType=CT_SINGLE; cbCardType<CT_BOMB_CARD; ++cbCardType)
    {
        tagOutCardTypeResult const &tmpCardResult = CardTypeResult[cbCardType] ;
        for(BYTE i=0; i<tmpCardResult.cbCardTypeCount; ++i)
        {
            if ( CompareCard(tmpCardResult.cbCardData[i], m_cbAllCardData[m_wBankerUser], tmpCardResult.cbEachHandCardCount[i], m_cbUserCardCount[m_wBankerUser]) )
                continue ;
            
            if ( tmpCardResult.cbEachHandCardCount[i] != cbHandCardCount && cbCardType >= CT_SINGLE_LINE && cbCardType <= CT_THREE_LINE_TAKE_TWO &&
                ( GetCardLogicValue(tmpCardResult.cbCardData[i][tmpCardResult.cbEachHandCardCount[i]-1]) > GetCardLogicValue(cbHandCardData[cbHandCardCount-2]) ||
                 GetCardLogicValue(tmpCardResult.cbCardData[i][0]) >= 11 ))
            {
                BYTE cbRemainCardData[MAX_COUNT], cbRemainCardCount ;
                CopyMemory(cbRemainCardData, cbHandCardData, cbHandCardCount) ;
                cbRemainCardCount = cbHandCardCount ;
                
                RemoveCard(tmpCardResult.cbCardData[i], tmpCardResult.cbEachHandCardCount[i], cbRemainCardData, cbRemainCardCount) ;
                cbRemainCardCount -= tmpCardResult.cbEachHandCardCount[i] ;
                
                BYTE cbCurrentLargestLogicCard = GetCardLogicValue(tmpCardResult.cbCardData[i][0]) ;
                
                if (GetCardType(cbRemainCardData, cbRemainCardCount) == CT_ERROR && (cbCardType >= CT_THREE_LINE_TAKE_ONE &&
                                                                                     cbCardType <= CT_THREE_LINE_TAKE_TWO && cbCurrentLargestLogicCard >= 11 && tmpCardResult.cbEachHandCardCount[i] <=5 ||
                                                                                     cbCardType == CT_SINGLE_LINE && tmpCardResult.cbEachHandCardCount[i] <= 6 && cbCurrentLargestLogicCard >= 12 ||
                                                                                     cbCardType >= CT_DOUBLE_LINE && cbCardType <= CT_THREE_LINE && cbCurrentLargestLogicCard >= 12 && tmpCardResult.cbEachHandCardCount[i] <= 8))
                {
                    if ( cbCardType >= CT_SINGLE_LINE && cbCardType <= CT_THREE_LINE &&
                        GetCardLogicValue(tmpCardResult.cbCardData[i][tmpCardResult.cbEachHandCardCount[i] - 1]) > GetCardLogicValue(cbHandCardData[cbHandCardCount-3]) )
                        continue ;
                    
                    if ( cbCardType >= CT_THREE_LINE_TAKE_ONE && cbCardType <= CT_THREE_LINE_TAKE_TWO &&
                        GetCardLogicValue(tmpCardResult.cbCardData[i][0]) > GetCardLogicValue(cbHandCardData[cbHandCardCount-3]) )
                        continue ;
                }
            }
            
            BYTE cbTmpCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, tmpCardResult.cbCardData[i], tmpCardResult.cbEachHandCardCount[i]) ;
            
            BYTE cbMaxValue=0 ;
            BYTE Index = 0 ;
            
            for(BYTE j=0; j<4; ++j)
            {
                if(cbMinSingleCardCount[j]>=cbTmpCount)
                {
                    cbMinSingleCardCount[j] = cbTmpCount ;
                    cbIndex[j] = i ;
                    cbOutcardType[j] = cbCardType ;
                    break ;
                }
            }
            
            if(cbMinSingleCountInFour>=cbTmpCount)
            {
                cbMinCardType = cbCardType ;
                cbMinSingleCountInFour=cbTmpCount ;
                cbMinIndex=i ;
            }
        }
    }
    
    if(cbMinSingleCountInFour!=MAX_COUNT)
    {
        BYTE Index = cbMinIndex ;
        
        for(BYTE i=0; i<4; ++i)
        {
            printf("ﾳ￶ￅￆ4");
            if(cbOutcardType[i]==cbMinCardType && cbMinSingleCardCount[i]<=cbMinSingleCountInFour &&
               GetCardLogicValue(CardTypeResult[cbMinCardType].cbCardData[cbIndex[i]][0])<GetCardLogicValue(CardTypeResult[cbMinCardType].cbCardData[Index][0]))
                Index = cbIndex[i] ;
        }
        
        if(cbHandCardCount==3 && GetCardColor(cbHandCardData[0])==0x40 && GetCardColor(cbHandCardData[1])==0x40)
        {
            OutCardResult.cbCardCount = 2 ;
            OutCardResult.cbResultCard[0] = 0x4F ;
            OutCardResult.cbResultCard[1] = 0x4E ;
            return ;
        }
        else if(cbHandCardCount==2 && GetCardColor(cbHandCardData[0])==0x40 && GetCardColor(cbHandCardData[1])==0x40)
        {
            OutCardResult.cbCardCount = 2 ;
            OutCardResult.cbResultCard[0] = 0x4F ;
            OutCardResult.cbResultCard[1] = 0x4E ;
            return ;
        }
        else
        {
            printf("ﾳ￶ￅￆ5");
            OutCardResult.cbCardCount=CardTypeResult[cbMinCardType].cbEachHandCardCount[Index];
            CopyMemory(OutCardResult.cbResultCard,CardTypeResult[cbMinCardType].cbCardData[Index],CardTypeResult[cbMinCardType].cbEachHandCardCount[Index]*sizeof(BYTE));
            return ;
        }
        return ;
    }
    else if (CardTypeResult[CT_BOMB_CARD].cbCardTypeCount > 0)
    {
        
    }
    
    BYTE cbAllSingleCardData[MAX_COUNT], cbAllSingleCardCount ;
    cbAllSingleCardCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, NULL, 0, cbAllSingleCardData) ;
    
    if ( cbAllSingleCardCount > 0 )
    {
        OutCardResult.cbCardCount = 1 ;
        OutCardResult.cbResultCard[0] = cbAllSingleCardData[cbAllSingleCardCount-1] ;
        
        return ;
    }
    
    OutCardResult.cbCardCount = 1 ;
    OutCardResult.cbResultCard[0] = cbHandCardData[cbHandCardCount-1] ;
    return ;
}
void DDZCGameLogicSingle::UndersideOfBankerOutCard(const BYTE cbHandCardData[], BYTE cbHandCardCount, WORD wOutCardUser, const BYTE cbTurnCardData[], BYTE cbTurnCardCount, tagOutCardResult & OutCardResult)
{
	ZeroMemory(&OutCardResult, sizeof(OutCardResult)) ;
    
	tagOutCardTypeResult CardTypeResult[12+1] ;
	ZeroMemory(CardTypeResult, sizeof(CardTypeResult)) ;
    
	BYTE cbOutCardType = GetCardType(cbTurnCardData,cbTurnCardCount) ;
    
	tagOutCardTypeResult BankerOutCardTypeResult[13] ;
	ZeroMemory(BankerOutCardTypeResult, sizeof(BankerOutCardTypeResult)) ;
    
	AnalyseOutCardType(m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser], BankerOutCardTypeResult) ;
	AnalyseOutCardType(cbHandCardData,cbHandCardCount,cbTurnCardData,cbTurnCardCount, CardTypeResult) ;
    
	printf("CardTypeResult[CT_BOMB_CARD].cbCardTypeCount=%d\n",CardTypeResult[CT_BOMB_CARD].cbCardTypeCount);
    
	if(cbHandCardCount==CardTypeResult[CT_BOMB_CARD].cbEachHandCardCount[0] && (cbOutCardType<CT_BOMB_CARD ||
                                                                                GetCardLogicValue(CardTypeResult[CT_BOMB_CARD].cbCardData[0][0])>GetCardLogicValue(cbTurnCardData[0])))
	{
		OutCardResult.cbCardCount = CardTypeResult[CT_BOMB_CARD].cbEachHandCardCount[0] ;
		CopyMemory(OutCardResult.cbResultCard,  CardTypeResult[CT_BOMB_CARD].cbCardData, OutCardResult.cbCardCount) ;
        
		return ;
	}
	else if(cbHandCardCount>2 && cbHandCardData[0]==0x4F && cbHandCardData[1]==0x4E && CT_ERROR!=GetCardType(cbHandCardData+2, cbHandCardCount-2) &&
            CT_FOUR_LINE_TAKE_ONE != GetCardType(cbHandCardData+2, cbHandCardCount-2) && CT_FOUR_LINE_TAKE_TWO != GetCardType(cbHandCardData+2, cbHandCardCount-2))
	{
		OutCardResult.cbCardCount = 2 ;
		OutCardResult.cbResultCard[0] = 0x4F ;
		OutCardResult.cbResultCard[1] = 0x4E ;
		return ;
	}
    
	BYTE cbRemainCard[MAX_COUNT], cbRemainCount=0;
	BYTE cbAllBombCard[MAX_COUNT], cbAllBombCount=0 ;
	GetAllBomCard(cbHandCardData, cbHandCardCount, cbAllBombCard, cbAllBombCount) ;
    
	if(cbAllBombCount>0 && wOutCardUser==m_wBankerUser)
	{
		CopyMemory(cbRemainCard, cbHandCardData, cbHandCardCount) ;
		cbRemainCount = cbHandCardCount ;
		RemoveCard(cbAllBombCard, cbAllBombCount, cbRemainCard, cbRemainCount) ;
		cbRemainCount -= cbAllBombCount ;
        
		if(CT_ERROR != GetCardType(cbRemainCard, cbRemainCount) ||
           (2==cbRemainCount && GetCardLogicValue(cbRemainCard[0])>GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0])))
		{
			if((cbOutCardType<CT_BOMB_CARD || GetCardLogicValue(cbAllBombCard[0])>GetCardLogicValue(cbTurnCardData[0])) &&
               ( CardTypeResult[cbOutCardType].cbCardTypeCount <= 0 || CT_ERROR != GetCardType(cbRemainCard, cbRemainCount)) )
			{
				if(GetCardColor(cbAllBombCard[0])==0x40)
				{
					OutCardResult.cbCardCount = 2 ;
					OutCardResult.cbResultCard[0] = 0x4F ;
					OutCardResult.cbResultCard[1] = 0x4E ;
					return ;
				}
				else
				{
					BYTE cbBankerAllBombCard[MAX_COUNT], cbBankerAllBombCardCount ;
					GetAllBomCard( m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser], cbBankerAllBombCard, cbBankerAllBombCardCount) ;
                    
					if ( !CompareCard( cbTurnCardData, cbRemainCard, cbTurnCardCount, cbRemainCount) ||  cbBankerAllBombCardCount <= 0 ||
						GetCardLogicValue( cbAllBombCard[0] ) > GetCardLogicValue( cbBankerAllBombCard[0] ) )
					{
						OutCardResult.cbCardCount = 4 ;
						CopyMemory(OutCardResult.cbResultCard, cbAllBombCard, 4) ;
						return ;
					}
				}
			}
		}
	}
    
	if ( CardTypeResult[CT_BOMB_CARD].cbCardTypeCount > 0 && GetCardType(m_cbAllCardData[(m_wBankerUser + 2) % GAME_PLAYER], m_cbUserCardCount[(m_wBankerUser + 2) % GAME_PLAYER]) != CT_ERROR &&
		GetCardType(m_cbAllCardData[(m_wBankerUser + 2) % GAME_PLAYER], m_cbUserCardCount[(m_wBankerUser + 2) % GAME_PLAYER]) <= CT_DOUBLE )
	{
		if ( GetCardType(m_cbAllCardData[(m_wBankerUser + 2) % GAME_PLAYER], m_cbUserCardCount[(m_wBankerUser + 2) % GAME_PLAYER]) == CT_SINGLE )
		{
			BYTE cbIndex = CardTypeResult[CT_BOMB_CARD].cbCardTypeCount - 1 ;
			BYTE cbCardCount = CardTypeResult[CT_BOMB_CARD].cbEachHandCardCount[cbIndex] ;
			CopyMemory(OutCardResult.cbResultCard, CardTypeResult[CT_BOMB_CARD].cbCardData[cbIndex], cbCardCount) ;
			OutCardResult.cbCardCount = cbCardCount ;
            
			return ;
		}
		else if ( GetCardType(m_cbAllCardData[(m_wBankerUser + 2) % GAME_PLAYER], m_cbUserCardCount[(m_wBankerUser + 2) % GAME_PLAYER]) == CT_DOUBLE )
		{
			BYTE cbAllDoubleCard[MAX_COUNT], cbAllDoubleCount ;
			GetAllDoubleCard(cbHandCardData, cbHandCardCount, cbAllDoubleCard, cbAllDoubleCount) ;
            
			if ( cbAllDoubleCount > 0 && GetCardLogicValue(cbAllDoubleCard[cbAllDoubleCount - 1]) <= 10)
			{
				BYTE cbIndex = CardTypeResult[CT_BOMB_CARD].cbCardTypeCount - 1 ;
				BYTE cbCardCount = CardTypeResult[CT_BOMB_CARD].cbEachHandCardCount[cbIndex] ;
				CopyMemory(OutCardResult.cbResultCard, CardTypeResult[CT_BOMB_CARD].cbCardData[cbIndex], cbCardCount) ;
				OutCardResult.cbCardCount = cbCardCount ;
                
				return ;
			}
		}
        
	}
    
	printf("%d\n",GetCardType(cbHandCardData, cbHandCardCount),CompareCard(cbTurnCardData, cbHandCardData, cbTurnCardCount, cbHandCardCount));
 	if ( GetCardType(cbHandCardData, cbHandCardCount) != CT_FOUR_LINE_TAKE_ONE && GetCardType(cbHandCardData, cbHandCardCount) != CT_FOUR_LINE_TAKE_TWO
		&& GetCardType(cbHandCardData,cbHandCardCount) != CT_ERROR && CompareCard(cbTurnCardData, cbHandCardData, cbTurnCardCount, cbHandCardCount) )
	{
		OutCardResult.cbCardCount = cbHandCardCount ;
		CopyMemory(OutCardResult.cbResultCard, cbHandCardData, cbHandCardCount) ;
        
		return ;
	}
    
	if (1 == m_cbUserCardCount[m_wBankerUser] && cbHandCardCount >= 2 && cbOutCardType == CT_DOUBLE)
	{
		tagAnalyseResultA AnalyseResult ;
		ZeroMemory(&AnalyseResult, sizeof(AnalyseResult)) ;
        
		AnalysebCardDataA(cbHandCardData, cbHandCardCount, AnalyseResult) ;
        
		if (cbHandCardCount == (AnalyseResult.bDoubleCount * 2 + AnalyseResult.bThreeCount * 3 + AnalyseResult.bFourCount * 4) ||
			cbHandCardCount == (AnalyseResult.bDoubleCount * 2 + AnalyseResult.bThreeCount * 3 + AnalyseResult.bFourCount * 4 + 1))
		{
			for (int nIndex = AnalyseResult.bDoubleCount-1; nIndex>=0 ; --nIndex)
			{
				if (GetCardLogicValue(AnalyseResult.m_bDCardData[nIndex*2]) > GetCardLogicValue(cbTurnCardData[0]))
				{
					OutCardResult.cbCardCount = 2 ;
					OutCardResult.cbResultCard[0] = AnalyseResult.m_bDCardData[nIndex*2] ;
					OutCardResult.cbResultCard[1] = AnalyseResult.m_bDCardData[nIndex*2+1] ;
					return ;
				}
			}
            
			if (AnalyseResult.bFourCount > 0)
			{
				BYTE cbLestBombIndex = AnalyseResult.bFourCount-1 ;
                
				OutCardResult.cbCardCount = 4 ;
				OutCardResult.cbResultCard[0] = AnalyseResult.m_bFCardData[cbLestBombIndex*4] ;
				OutCardResult.cbResultCard[1] = AnalyseResult.m_bFCardData[cbLestBombIndex*4+1] ;
				OutCardResult.cbResultCard[2] = AnalyseResult.m_bFCardData[cbLestBombIndex*4+2] ;
				OutCardResult.cbResultCard[3] = AnalyseResult.m_bFCardData[cbLestBombIndex*4+3] ;
                
				return ;
			}
            
		}
        
		if ( wOutCardUser != m_wBankerUser )
		{
			tagAnalyseResultA FriendAnalyseResult ;
			ZeroMemory( &FriendAnalyseResult, sizeof( FriendAnalyseResult ) ) ;
            
			AnalysebCardDataA( m_cbAllCardData[wOutCardUser], m_cbUserCardCount[wOutCardUser], FriendAnalyseResult ) ;
            
			if ( m_cbUserCardCount[wOutCardUser] == (FriendAnalyseResult.bDoubleCount * 2 + FriendAnalyseResult.bThreeCount * 3 + FriendAnalyseResult.bFourCount * 4) ||
				m_cbUserCardCount[wOutCardUser] == (FriendAnalyseResult.bDoubleCount * 2 + FriendAnalyseResult.bThreeCount * 3 + FriendAnalyseResult.bFourCount * 4 + 1))
			{
				return ;
			}
            
			tagOutCardTypeResult FriendCardTypeResult[12+1] ;
			ZeroMemory( FriendCardTypeResult, sizeof( FriendCardTypeResult ) ) ;
            
			AnalyseOutCardType( m_cbAllCardData[wOutCardUser], m_cbUserCardCount[wOutCardUser], FriendCardTypeResult ) ;
            
			for ( BYTE cbLineCardIdx = 0; cbLineCardIdx < FriendCardTypeResult[CT_SINGLE_LINE].cbCardTypeCount; ++cbLineCardIdx )
			{
				BYTE cbRemainCardData[MAX_COUNT], cbRemainCardCount ;
                
				cbRemainCardCount = m_cbUserCardCount[wOutCardUser] ;
				CopyMemory( cbRemainCardData, m_cbAllCardData[wOutCardUser], cbRemainCardCount ) ;
				RemoveCard( FriendCardTypeResult[CT_SINGLE_LINE].cbCardData[cbLineCardIdx],  FriendCardTypeResult[CT_SINGLE_LINE].cbEachHandCardCount[cbLineCardIdx],
                           cbRemainCardData, cbRemainCardCount ) ;
                
				cbRemainCardCount -= FriendCardTypeResult[CT_SINGLE_LINE].cbEachHandCardCount[cbLineCardIdx] ;
                
				AnalysebCardDataA( cbRemainCardData, cbRemainCardCount, FriendAnalyseResult ) ;
                
				if (cbRemainCardCount == (FriendAnalyseResult.bDoubleCount * 2 + FriendAnalyseResult.bThreeCount * 3 + FriendAnalyseResult.bFourCount * 4) ||
					cbRemainCardCount == (FriendAnalyseResult.bDoubleCount * 2 + FriendAnalyseResult.bThreeCount * 3 + FriendAnalyseResult.bFourCount * 4 + 1))
				{
					return ;
				}
			}
            
			for ( BYTE cbLineCardIdx = 0; cbLineCardIdx < FriendCardTypeResult[CT_DOUBLE_LINE].cbCardTypeCount; ++cbLineCardIdx )
			{
				BYTE cbRemainCardData[MAX_COUNT], cbRemainCardCount ;
                
				cbRemainCardCount = m_cbUserCardCount[wOutCardUser] ;
				CopyMemory( cbRemainCardData, m_cbAllCardData[wOutCardUser], cbRemainCardCount ) ;
				RemoveCard( FriendCardTypeResult[CT_SINGLE_LINE].cbCardData[cbLineCardIdx],  FriendCardTypeResult[CT_SINGLE_LINE].cbEachHandCardCount[cbLineCardIdx],
                           cbRemainCardData, cbRemainCardCount ) ;
                
				cbRemainCardCount -= FriendCardTypeResult[CT_SINGLE_LINE].cbEachHandCardCount[cbLineCardIdx] ;
                
				AnalysebCardDataA( cbRemainCardData, cbRemainCardCount, FriendAnalyseResult ) ;
                
				if (cbRemainCardCount == (FriendAnalyseResult.bDoubleCount * 2 + FriendAnalyseResult.bThreeCount * 3 + FriendAnalyseResult.bFourCount * 4) ||
					cbRemainCardCount == (FriendAnalyseResult.bDoubleCount * 2 + FriendAnalyseResult.bThreeCount * 3 + FriendAnalyseResult.bFourCount * 4 + 1))
				{
					return ;
				}
			}
            
            
		}
	}
    
    
	if( m_wBankerUser != wOutCardUser && ! CompareCard( cbTurnCardData, m_cbAllCardData[ m_wBankerUser ], cbTurnCardCount, m_cbUserCardCount[ m_wBankerUser ] ) )
	{
		bool bBankerCanOut = false ;
		tagOutCardTypeResult BankerOutCardResult[12+1] ;
		ZeroMemory(BankerOutCardResult, sizeof(BankerOutCardResult)) ;
        
		AnalyseOutCardType(m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser], cbTurnCardData, cbTurnCardCount, BankerOutCardResult) ;
		for(BYTE cbCardType=CT_SINGLE; cbCardType<=CT_MISSILE_CARD; ++cbCardType) if(BankerOutCardResult[cbCardType].cbCardTypeCount>0) bBankerCanOut = true ;
        
		if(!bBankerCanOut)
		{
			WORD wFriendChairID = (m_wBankerUser+2)%GAME_PLAYER ;
            
			tagOutCardTypeResult FriendCardTypeResult[12+1] ;
			ZeroMemory(FriendCardTypeResult, sizeof(FriendCardTypeResult)) ;
			AnalyseOutCardType(m_cbAllCardData[wFriendChairID], m_cbUserCardCount[wFriendChairID], FriendCardTypeResult) ;
            
			for(BYTE cbCardType=CT_SINGLE; cbCardType<=CT_MISSILE_CARD; ++cbCardType)
				if(FriendCardTypeResult[cbCardType].cbCardTypeCount>0)
				{
					for(long lIndex=0; lIndex<FriendCardTypeResult[cbCardType].cbCardTypeCount; ++lIndex)
					{
                        
						if(TestOutAllCard(wFriendChairID, FriendCardTypeResult[cbCardType].cbCardData[lIndex], FriendCardTypeResult[cbCardType].cbEachHandCardCount[lIndex], true))
						{
							return ;
						}
					}
				}
		}
	}
    
	if (GetCardType(m_cbAllCardData[(m_wBankerUser + 2) % GAME_PLAYER], m_cbUserCardCount[(m_wBankerUser + 2) % GAME_PLAYER]) == GetCardType(cbTurnCardData, cbTurnCardCount) &&
		CompareCard(cbTurnCardData, m_cbAllCardData[(m_wBankerUser + 2) % GAME_PLAYER], cbTurnCardCount, m_cbUserCardCount[(m_wBankerUser + 2) % GAME_PLAYER]))
		return ;
    
	if (CompareCard(cbTurnCardData, m_cbAllCardData[(m_wBankerUser + 2) % GAME_PLAYER], cbTurnCardCount, m_cbUserCardCount[(m_wBankerUser + 2) % GAME_PLAYER])) return ;
    
	BYTE cbSingleCardCount = MAX_COUNT+CT_MISSILE_CARD ;
	bool bFindBestCard = false ;
	for(BYTE cbCardType=CT_SINGLE; cbCardType<=CT_MISSILE_CARD; ++cbCardType)
		if(CardTypeResult[cbCardType].cbCardTypeCount>0)
		{
			for(long lIndex=0; lIndex<CardTypeResult[cbCardType].cbCardTypeCount; ++lIndex)
			{
				WORD wMeChairID = (m_wBankerUser+1)%GAME_PLAYER ;
                
				if(TestOutAllCard(wMeChairID, CardTypeResult[cbCardType].cbCardData[lIndex], CardTypeResult[cbCardType].cbEachHandCardCount[lIndex], false))
				{
					BYTE cbTmpSingleCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, CardTypeResult[cbCardType].cbCardData[lIndex],
                                                                  CardTypeResult[cbCardType].cbEachHandCardCount[lIndex]) ;
                    
					if (cbTmpSingleCount >= MAX_COUNT) continue ;
                    
					BYTE cbBombCardType = GetCardType(CardTypeResult[cbCardType].cbCardData[lIndex], CardTypeResult[cbCardType].cbEachHandCardCount[lIndex]) ;
					if (cbBombCardType == CT_BOMB_CARD) cbTmpSingleCount += 4 ;
					else if (cbBombCardType == CT_MISSILE_CARD) cbTmpSingleCount += 5 ;
                    
                    
					if(cbTmpSingleCount <= cbSingleCardCount)
					{
						OutCardResult.cbCardCount=CardTypeResult[cbCardType].cbEachHandCardCount[lIndex];
						CopyMemory(OutCardResult.cbResultCard, CardTypeResult[cbCardType].cbCardData[lIndex],
                                   CardTypeResult[cbCardType].cbEachHandCardCount[lIndex]*sizeof(BYTE));
						cbSingleCardCount = cbTmpSingleCount ;
						bFindBestCard = true ;
					}
				}
			}
		}
    if (bFindBestCard) return ;
    
    BYTE cbMinSingleCardCount[4] ;
    cbMinSingleCardCount[0]=MAX_COUNT ;
    cbMinSingleCardCount[1]=MAX_COUNT ;
    cbMinSingleCardCount[2]=MAX_COUNT ;
    cbMinSingleCardCount[3]=MAX_COUNT ;
    BYTE cbIndex[4]={0} ;
    BYTE cbMinSingleCountInFour=MAX_COUNT ;
    
    tagOutCardTypeResult const &CanOutCard = CardTypeResult[cbOutCardType] ;
    
    for(BYTE i=0; i<CanOutCard.cbCardTypeCount; ++i)
    {
        BYTE cbTmpCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount,CanOutCard.cbCardData[i], CanOutCard.cbEachHandCardCount[i]) ;
        BYTE cbMaxValue=0 ;
        BYTE Index = 0 ;
        
        for(BYTE j=0; j<4; ++j)
        {
            if(cbMinSingleCardCount[j]>=cbTmpCount)
            {
                cbMinSingleCardCount[j] = cbTmpCount ;
                cbIndex[j] = i ;
                break ;
            }
        }
        
    }
    
    for(BYTE i=0; i<4; ++i)
        if(cbMinSingleCountInFour>cbMinSingleCardCount[i]) cbMinSingleCountInFour = cbMinSingleCardCount[i] ;
    
    
    BYTE cbOriginSingleCardCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount,NULL,0) ;
    
    bool bFriendOut = m_wBankerUser!=wOutCardUser ;
    if(bFriendOut)
    {
        if (GetCardType(m_cbAllCardData[(2 + m_wBankerUser) % GAME_PLAYER], m_cbUserCardCount[(2 + m_wBankerUser) % GAME_PLAYER]) != CT_ERROR) return ;
        
        if(CanOutCard.cbCardTypeCount > 0 && CanOutCard.cbCardType < CT_BOMB_CARD &&  cbMinSingleCountInFour < MAX_COUNT)
        {
            BYTE cbMinLogicCardValue = GetCardLogicValue(0x4F)+1 ;
            bool bFindCard = false ;
            BYTE cbCanOutIndex=0 ;
            for(BYTE i=0; i<4; ++i)
            {
                BYTE Index = cbIndex[i] ;
                
                if ( CanOutCard.cbCardType >= CT_THREE &&  CanOutCard.cbCardType <= CT_MISSILE_CARD && GetCardLogicValue(CanOutCard.cbCardData[Index][0]) >= 7 &&
                    CanOutCard.cbEachHandCardCount[Index] <=5 )
                    continue ;
                
                if((cbMinSingleCardCount[i]<cbOriginSingleCardCount+3 &&  (cbMinSingleCardCount[i]<=cbMinSingleCountInFour || cbMinSingleCardCount[i]<=cbMinSingleCountInFour+1 &&
                                                                           CanOutCard.cbCardType >= CT_THREE_LINE_TAKE_ONE && CanOutCard.cbCardType <= CT_THREE_LINE_TAKE_TWO ) &&
                    (GetCardLogicValue(CanOutCard.cbCardData[Index][0])<=11 || (cbMinSingleCardCount[i]<cbOriginSingleCardCount)&&GetCardLogicValue(CanOutCard.cbCardData[Index][0])<=13)) &&
                   cbMinLogicCardValue>GetCardLogicValue(CanOutCard.cbCardData[Index][0]) && cbHandCardCount>5)
                {
                    bool bNoLargeCard = true ;
                    for(BYTE k=3; k<CanOutCard.cbEachHandCardCount[Index]; ++k)
                    {
                        if(GetCardLogicValue(CanOutCard.cbCardData[Index][k])>=15 &&
                           CanOutCard.cbEachHandCardCount[Index]!=cbHandCardCount) bNoLargeCard = false ;
                    }
                    if(bNoLargeCard)
                    {
                        bFindCard = true ;
                        cbCanOutIndex = Index ;
                        cbMinLogicCardValue = GetCardLogicValue(CanOutCard.cbCardData[Index][0]) ;
                    }
                }
                else if(cbHandCardCount<5 && cbMinSingleCardCount[i]<cbOriginSingleCardCount+4 && cbMinSingleCardCount[i]<=cbMinSingleCountInFour &&
						cbMinLogicCardValue>GetCardLogicValue(CanOutCard.cbCardData[Index][0]))
                {
                    if ( GetCardLogicValue( CanOutCard.cbCardData[Index][0] ) >= 16 && GetCardLogicValue( cbTurnCardData[0] ) >= 15 )
                        continue ;
                    
                    bFindCard = true ;
                    cbCanOutIndex = Index ;
                    cbMinLogicCardValue = GetCardLogicValue(CanOutCard.cbCardData[Index][0]) ;
                }
            }
            
            if(bFindCard)
            {
                
                OutCardResult.cbCardCount=CanOutCard.cbEachHandCardCount[cbCanOutIndex];
                CopyMemory(OutCardResult.cbResultCard,CanOutCard.cbCardData[cbCanOutIndex],CanOutCard.cbEachHandCardCount[cbCanOutIndex]*sizeof(BYTE));
                
                return ;
            }
            else if(cbHandCardCount<=5)
            {
                BYTE cbMinLogicCard = GetCardLogicValue(0x4F)+1 ;
                BYTE cbCanOutIndex = 0 ;
                for(BYTE i=0; i<4; ++i)
                    if(cbMinSingleCardCount[i]<MAX_COUNT && cbMinSingleCardCount[i]<=cbMinSingleCountInFour && cbMinLogicCard>GetCardLogicValue(CanOutCard.cbCardData[cbIndex[i]][0]) &&
                       GetCardLogicValue(CanOutCard.cbCardData[cbIndex[i]][0])<=14)
                    {
                        cbMinLogicCard = GetCardLogicValue(CanOutCard.cbCardData[cbIndex[i]][0]) ;
                        cbCanOutIndex = cbIndex[i] ;
                    }
                
                if(cbMinLogicCard != (GetCardLogicValue(0x4F)+1))
                {
                    OutCardResult.cbCardCount=CanOutCard.cbEachHandCardCount[cbCanOutIndex];
                    CopyMemory(OutCardResult.cbResultCard,CanOutCard.cbCardData[cbCanOutIndex],CanOutCard.cbEachHandCardCount[cbCanOutIndex]*sizeof(BYTE));
                    
                    return ;
                }
            }
            
            return ;
        }
        else
        {
            return ;
        }
        
    }
    else
    {
        if(CanOutCard.cbCardTypeCount>0 && cbMinSingleCountInFour < MAX_COUNT)
        {
            BYTE cbMinLogicCardValue = GetCardLogicValue(0x4F)+1 ;
            bool bFindCard = false ;
            BYTE cbCanOutIndex=0 ;
            for(BYTE i=0; i<4; ++i)
            {
                BYTE Index = cbIndex[i] ;
                
                if((cbMinSingleCardCount[i]<cbOriginSingleCardCount+4)  &&  (cbMinSingleCardCount[i]<=cbMinSingleCountInFour || cbMinSingleCardCount[i]<=cbMinSingleCountInFour+1 &&
                                                                             CanOutCard.cbCardType >= CT_THREE_LINE_TAKE_ONE && CanOutCard.cbCardType <= CT_THREE_LINE_TAKE_TWO ) &&
                   cbMinLogicCardValue>GetCardLogicValue(CanOutCard.cbCardData[Index][0]))
                {
                    bool bNoLargeCard = true ;
                    
                    if(m_cbUserCardCount[m_wBankerUser]>=4 && cbHandCardCount>=5 && CanOutCard.cbEachHandCardCount[Index]>=2 &&
                       GetCardLogicValue(CanOutCard.cbCardData[Index][0])>=15 &&
                       GetCardLogicValue(cbTurnCardData[0])<13 &&
                       GetCardLogicValue(cbTurnCardData[0])<GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0]) &&
                       CanOutCard.cbEachHandCardCount[Index]!=cbHandCardCount)
                        bNoLargeCard=false ;
                    
                    for(BYTE k=3; k<CanOutCard.cbEachHandCardCount[Index]; ++k)
                    {
                        if(GetCardLogicValue(CanOutCard.cbCardData[Index][k])>=15 &&
                           CanOutCard.cbEachHandCardCount[Index]!=cbHandCardCount)
                            bNoLargeCard = false ;
                    }
                    if(bNoLargeCard)
                    {
                        bFindCard = true ;
                        cbCanOutIndex = Index ;
                        cbMinLogicCardValue = GetCardLogicValue(CanOutCard.cbCardData[Index][0]) ;
                    }
                }
            }
            
            if(bFindCard)
            {
                BYTE cbLargestLogicCard = GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0]) ;
                bool bCanOut=true ;
                
                if(GetCardLogicValue(cbTurnCardData[0])<cbLargestLogicCard)
                {
                    if(GetCardColor(CanOutCard.cbCardData[cbCanOutIndex][0])==0x40 && GetCardLogicValue(cbTurnCardData[0])<=14 && cbHandCardCount>5)
                    {
                        bCanOut = false ;
                    }
                }
                
                if(GetCardLogicValue(CanOutCard.cbCardData[cbCanOutIndex][0])>=16 && cbHandCardCount>=2 && cbHandCardData[0]==0x4F && cbHandCardData[1]==0x4E)
                {
                    bool bOutMissileCard = false ;
                    BYTE cbRemainCardData[20], cbRemainCardCount=cbHandCardCount ;
                    CopyMemory(cbRemainCardData, cbHandCardData, cbHandCardCount) ;
                    RemoveCard(cbRemainCardData, 2, cbRemainCardData, cbRemainCardCount) ;
                    cbRemainCardCount -= 2 ;
                    if(CT_ERROR!=GetCardType(cbRemainCardData, cbRemainCardCount)) bOutMissileCard = true;
                    
                    BYTE cbRemainLargestCard = GetCardLogicValue(cbRemainCardData[0]) ;
                    if(cbRemainCardCount<5 && cbRemainCardCount>0 && GetCardLogicValue(cbRemainCardData[0])>=14) bOutMissileCard = true;
                    
                    BYTE cbSingleCardCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, CanOutCard.cbCardData[cbCanOutIndex],
                                                                   CanOutCard.cbEachHandCardCount[cbCanOutIndex]) ;
                    if(cbSingleCardCount<=1 && GetCardLogicValue(cbRemainCardData[0])>=11) bOutMissileCard = true;
                    
                    if (GetCardLogicValue(cbRemainCardData[0]) <= 10 && CT_ERROR == GetCardType(cbRemainCardData, cbRemainCardCount) &&
                        GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0]) > 10)
                        bOutMissileCard = false ;
                    
                    if(bOutMissileCard)
                    {
                        BYTE cbIndex = CardTypeResult[CT_BOMB_CARD].cbCardTypeCount - 1 ;
                        
                        OutCardResult.cbCardCount = CardTypeResult[CT_BOMB_CARD].cbEachHandCardCount[cbIndex] ;
                        CopyMemory(OutCardResult.cbResultCard, CardTypeResult[CT_BOMB_CARD].cbCardData[cbIndex], OutCardResult.cbCardCount) ;
                        return ;
                    }
                }
                if(bCanOut)
                {
                    OutCardResult.cbCardCount=CanOutCard.cbEachHandCardCount[cbCanOutIndex];
                    CopyMemory(OutCardResult.cbResultCard,CanOutCard.cbCardData[cbCanOutIndex],CanOutCard.cbEachHandCardCount[cbCanOutIndex]*sizeof(BYTE));
                    
                    return ;
                }
            }
            
            if(cbOutCardType==CT_SINGLE)
            {
                BYTE cbLargestLogicCard = GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0]) ;
                
                if(GetCardLogicValue(cbTurnCardData[0])==14 ||
                   GetCardLogicValue(cbTurnCardData[0])>=cbLargestLogicCard ||
                   (GetCardLogicValue(cbTurnCardData[0])<cbLargestLogicCard-1) ||
                   m_cbUserCardCount[m_wBankerUser]<=5)
                {
                    BYTE cbIndex=MAX_COUNT ;
                    for(BYTE i=0; i<cbHandCardCount; ++i)
                        if(GetCardLogicValue(cbHandCardData[i])>GetCardLogicValue(cbTurnCardData[0]) &&
                           GetCardLogicValue(cbHandCardData[i])>=15)
                        {
                            cbIndex = i ;
                        }
                    if(cbIndex!=MAX_COUNT)
                    {
                        OutCardResult.cbCardCount=1;
                        OutCardResult.cbResultCard[0] = cbHandCardData[cbIndex] ;
                        
                        return ;
                    }
                }
            }
            WORD wMeChairID = (m_wBankerUser+1)%GAME_PLAYER ;
            WORD wFriendID = (wMeChairID+1)%GAME_PLAYER ;
            
            tagOutCardTypeResult FriendCardTypeResult[13] ;
            ZeroMemory(FriendCardTypeResult, sizeof(FriendCardTypeResult)) ;
            AnalyseOutCardType(m_cbAllCardData[wFriendID], m_cbUserCardCount[wFriendID], cbTurnCardData, cbTurnCardCount, FriendCardTypeResult) ;
            
            if(m_cbUserCardCount[m_wBankerUser]<=4 && FriendCardTypeResult[cbOutCardType].cbCardTypeCount==0 && CardTypeResult[cbOutCardType].cbCardTypeCount>0)
            {
                BYTE cbMinSingleCount=MAX_COUNT ;
                BYTE Index=0 ;
                for(BYTE i=0; i<CardTypeResult[cbOutCardType].cbCardTypeCount; ++i)
                {
                    BYTE cbTmpCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, CardTypeResult[cbOutCardType].cbCardData[i], CardTypeResult[cbOutCardType].cbEachHandCardCount[i]) ;
                    if(cbMinSingleCount>=cbTmpCount)
                    {
                        cbMinSingleCount = cbTmpCount ;
                        Index = i ;
                    }
                }
                OutCardResult.cbCardCount=CardTypeResult[cbOutCardType].cbEachHandCardCount[Index];
                CopyMemory(OutCardResult.cbResultCard, CardTypeResult[cbOutCardType].cbCardData[Index], OutCardResult.cbCardCount) ;
                
                return ;
            }
        }
        
        if(CardTypeResult[CT_BOMB_CARD].cbCardTypeCount>0 ||
           (NORMAL_COUNT  == cbHandCardCount && NORMAL_COUNT == m_cbUserCardCount[(m_wBankerUser+2)%GAME_PLAYER]))
        {
            tagOutCardTypeResult const &BomCard = CardTypeResult[CT_BOMB_CARD] ;
            BYTE cbMinLogicValue = GetCardLogicValue(BomCard.cbCardData[0][0]) ;
            BYTE Index = 0 ;
            for(BYTE i=0; i<BomCard.cbCardTypeCount; ++i)
            {
                if(cbMinLogicValue>GetCardLogicValue(BomCard.cbCardData[i][0]))
                {
                    cbMinLogicValue = GetCardLogicValue(BomCard.cbCardData[i][0]) ;
                    Index = i ;
                }
            }
            
            bool bOutBomb = false ;
            
            if (NORMAL_COUNT  == cbHandCardCount && NORMAL_COUNT == m_cbUserCardCount[(m_wBankerUser+2)%GAME_PLAYER] && CT_ERROR != GetCardType(m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser]))
                bOutBomb = true ;
            
            BYTE cbRemainCardData[20], cbRemainCardCount=cbHandCardCount ;
            CopyMemory(cbRemainCardData, cbHandCardData, cbHandCardCount) ;
            RemoveCard(BomCard.cbCardData[Index], BomCard.cbEachHandCardCount[Index], cbRemainCardData, cbRemainCardCount) ;
            cbRemainCardCount -= BomCard.cbEachHandCardCount[Index] ;
            if(CT_ERROR!=GetCardType(cbRemainCardData, cbRemainCardCount)) bOutBomb = true ;
            
            BYTE cbSingleCardCount = AnalyseSinleCardCount(cbHandCardData, cbHandCardCount, BomCard.cbCardData[Index],BomCard.cbEachHandCardCount[Index]) ;
            if(cbSingleCardCount==0 && GetCardLogicValue(cbRemainCardData[0]) > GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0]))
                bOutBomb = true ;
            
            BYTE cbRemainCardType = GetCardType(m_cbAllCardData[wOutCardUser], m_cbUserCardCount[wOutCardUser]) ;
            if(cbRemainCardType>CT_ERROR && cbRemainCardType<CT_FOUR_LINE_TAKE_ONE && GetCardLogicValue(m_cbAllCardData[wOutCardUser][0])<15 &&
               cbSingleCardCount < 2 && (GetCardLogicValue(cbRemainCardData[0]) >= GetCardLogicValue(m_cbAllCardData[m_wBankerUser][0])))
                bOutBomb = true ;
            
            BYTE cbRemainLargestCard = GetCardLogicValue(cbRemainCardData[0]) ;
            if(cbRemainCardCount<5 && cbRemainCardCount>0 && (cbRemainLargestCard!=GetCardLogicValue(BomCard.cbCardData[Index][0])) &&
               cbRemainLargestCard>GetCardLogicValue(m_cbAllCardData[wOutCardUser][0]) && cbRemainLargestCard > 14) bOutBomb = true ;
            
            tagAnalyseResultA AnalyseResult ;
            AnalysebCardDataA(cbRemainCardData, cbRemainCardCount, AnalyseResult) ;
            
            if (m_cbUserCardCount[m_wBankerUser] == 1 && (AnalyseResult.bDoubleCount * 2 + AnalyseResult.bThreeCount * 3 + AnalyseResult.bFourCount * 4 + 1 >= cbRemainCardCount)) bOutBomb = true ;
            
            
            if(bOutBomb)
            {
                OutCardResult.cbCardCount=BomCard.cbEachHandCardCount[Index];
                CopyMemory(OutCardResult.cbResultCard,BomCard.cbCardData[Index],BomCard.cbEachHandCardCount[Index]*sizeof(BYTE));
            }
            
            return ;
        }
        
        return ;
    }
    return ;
}

void DDZCGameLogicSingle::AnalysebCardData(const BYTE cbCardData[], BYTE cbCardCount, tagAnalyseResult & AnalyseResult)
{
	ZeroMemory(&AnalyseResult,sizeof(AnalyseResult));
    
	for (BYTE i=0;i<cbCardCount;i++)
	{
		BYTE cbSameCount=1,cbCardValueTemp=0;
		BYTE cbLogicValue=GetCardLogicValue(cbCardData[i]);
        
		for (BYTE j=i+1;j<cbCardCount;j++)
		{
			if (GetCardLogicValue(cbCardData[j])!=cbLogicValue) break;
            
			cbSameCount++;
		}
        
		BYTE cbIndex=AnalyseResult.cbBlockCount[cbSameCount-1]++;
		for (BYTE j=0;j<cbSameCount;j++) AnalyseResult.cbCardData[cbSameCount-1][cbIndex*cbSameCount+j]=cbCardData[i+j];
        
		i+=cbSameCount-1;
	}
    
	return;
}

void DDZCGameLogicSingle::AnalysebCardDataA(const BYTE bCardData[], BYTE bCardCount, tagAnalyseResultA & AnalyseResult)
{
	BYTE bSameCount=1,bCardValueTemp=0;
	BYTE bLogicValue=GetCardLogicValue(bCardData[0]);
    
	memset(&AnalyseResult,0,sizeof(AnalyseResult));
    
	for (BYTE i=1;i<bCardCount;i++)
	{
		bCardValueTemp=GetCardLogicValue(bCardData[i]);
		if (bCardValueTemp==bLogicValue) bSameCount++;
        
		if ((bCardValueTemp!=bLogicValue)||(i==(bCardCount-1)))
		{
			switch (bSameCount)
			{
                case 2:
				{
					CopyMemory(&AnalyseResult.m_bDCardData[AnalyseResult.bDoubleCount*2],&bCardData[i-2+((i==bCardCount-1&&bCardValueTemp==bLogicValue)?1:0)],2);
					AnalyseResult.bDoubleLogicVolue[AnalyseResult.bDoubleCount++]=bLogicValue;
					break;
				}
                case 3:
				{
					CopyMemory(&AnalyseResult.m_bTCardData[AnalyseResult.bThreeCount*3],&bCardData[i-3+((i==bCardCount-1&&bCardValueTemp==bLogicValue)?1:0)],3);
					AnalyseResult.bThreeLogicVolue[AnalyseResult.bThreeCount++]=bLogicValue;
					break;
				}
                case 4:
				{
					CopyMemory(&AnalyseResult.m_bFCardData[AnalyseResult.bFourCount*4],&bCardData[i-4+((i==bCardCount-1&&bCardValueTemp==bLogicValue)?1:0)],4);
					AnalyseResult.bFourLogicVolue[AnalyseResult.bFourCount++]=bLogicValue;
					break;
				}
			}
		}
        
		if (bCardValueTemp!=bLogicValue)
		{
			if(bSameCount==1)
			{
				if(i!=bCardCount-1)
					AnalyseResult.m_bSCardData[AnalyseResult.bSignedCount++]=bCardData[i-1];
				else
				{
					AnalyseResult.m_bSCardData[AnalyseResult.bSignedCount++]=bCardData[i-1];
					AnalyseResult.m_bSCardData[AnalyseResult.bSignedCount++]=bCardData[i];
				}
			}
			else
			{
				if(i==bCardCount-1)
					AnalyseResult.m_bSCardData[AnalyseResult.bSignedCount++]=bCardData[i];
			}
			bSameCount=1;
			bLogicValue=bCardValueTemp;
            
		}
	}
    
	BYTE bOtherCount=AnalyseResult.bDoubleCount*2+AnalyseResult.bThreeCount*3+AnalyseResult.bFourCount*4;
	return;
}

void DDZCGameLogicSingle::AnalysebDistributing(const BYTE cbCardData[], BYTE cbCardCount, tagDistributing & Distributing)
{
	ZeroMemory(&Distributing,sizeof(Distributing));
    
	for (BYTE i=0;i<cbCardCount;i++)
	{
		if (cbCardData[i]==0) continue;
        
		BYTE cbCardColor=GetCardColor(cbCardData[i]);
		BYTE cbCardValue=GetCardValue(cbCardData[i]);
        
		Distributing.cbCardCount++;
		Distributing.cbDistributing[cbCardValue-1][cbIndexCount]++;
		Distributing.cbDistributing[cbCardValue-1][cbCardColor>>4]++;
	}
    
	return;
}

BYTE DDZCGameLogicSingle::SearchOutCard( const BYTE cbHandCardData[], BYTE cbHandCardCount, const BYTE cbTurnCardData[], BYTE cbTurnCardCount,
                                        tagSearchCardResult *pSearchCardResult )
{
	
	if( pSearchCardResult == NULL ) return 0;
    
	ZeroMemory(pSearchCardResult,sizeof(tagSearchCardResult));
    
	BYTE cbResultCount = 0;
	tagSearchCardResult tmpSearchCardResult = {};
    
	BYTE cbCardData[MAX_COUNT];
	BYTE cbCardCount=cbHandCardCount;
	CopyMemory(cbCardData,cbHandCardData,sizeof(BYTE)*cbHandCardCount);
    
	SortCardList(cbCardData,cbCardCount,ST_ORDER);
    
	BYTE cbTurnOutType=GetCardType(cbTurnCardData,cbTurnCardCount);
    
	switch (cbTurnOutType)
	{
        case CT_ERROR:
		{
			if( !pSearchCardResult ) return 0;
            
			if( GetCardType(cbCardData,cbCardCount) != CT_ERROR )
			{
				pSearchCardResult->cbCardCount[cbResultCount] = cbCardCount;
				CopyMemory( pSearchCardResult->cbResultCard[cbResultCount],cbCardData,
                           sizeof(BYTE)*cbCardCount );
				cbResultCount++;
			}
			BYTE cbSameCount = 0;
			if( cbCardCount > 1 && GetCardValue(cbCardData[cbCardCount-1]) == GetCardValue(cbCardData[cbCardCount-2]) )
			{
				cbSameCount = 1;
				pSearchCardResult->cbResultCard[cbResultCount][0] = cbCardData[cbCardCount-1];
				BYTE cbCardValue = GetCardValue(cbCardData[cbCardCount-1]);
				for( int i = cbCardCount-2; i >= 0; i-- )
				{
					if( GetCardValue(cbCardData[i]) == cbCardValue )
					{
						pSearchCardResult->cbResultCard[cbResultCount][cbSameCount++] = cbCardData[i];
					}
					else break;
				}
                
				pSearchCardResult->cbCardCount[cbResultCount] = cbSameCount;
				cbResultCount++;
			}
            
			BYTE cbTmpCount = 0;
			if( cbSameCount != 1 )
			{
				cbTmpCount = SearchSameCard( cbCardData,cbCardCount,0,1,&tmpSearchCardResult );
				if( cbTmpCount > 0 )
				{
					pSearchCardResult->cbCardCount[cbResultCount] = tmpSearchCardResult.cbCardCount[0];
					CopyMemory( pSearchCardResult->cbResultCard[cbResultCount],tmpSearchCardResult.cbResultCard[0],
                               sizeof(BYTE)*tmpSearchCardResult.cbCardCount[0] );
					cbResultCount++;
				}
			}
            
			if( cbSameCount != 2 )
			{
				cbTmpCount = SearchSameCard( cbCardData,cbCardCount,0,2,&tmpSearchCardResult );
				if( cbTmpCount > 0 )
				{
					pSearchCardResult->cbCardCount[cbResultCount] = tmpSearchCardResult.cbCardCount[0];
					CopyMemory( pSearchCardResult->cbResultCard[cbResultCount],tmpSearchCardResult.cbResultCard[0],
                               sizeof(BYTE)*tmpSearchCardResult.cbCardCount[0] );
					cbResultCount++;
				}
			}
            
			if( cbSameCount != 3 )
			{
				cbTmpCount = SearchSameCard( cbCardData,cbCardCount,0,3,&tmpSearchCardResult );
				if( cbTmpCount > 0 )
				{
					pSearchCardResult->cbCardCount[cbResultCount] = tmpSearchCardResult.cbCardCount[0];
					CopyMemory( pSearchCardResult->cbResultCard[cbResultCount],tmpSearchCardResult.cbResultCard[0],
                               sizeof(BYTE)*tmpSearchCardResult.cbCardCount[0] );
					cbResultCount++;
				}
			}
            
			cbTmpCount = SearchTakeCardType( cbCardData,cbCardCount,0,3,1,&tmpSearchCardResult );
			if( cbTmpCount > 0 )
			{
				pSearchCardResult->cbCardCount[cbResultCount] = tmpSearchCardResult.cbCardCount[0];
				CopyMemory( pSearchCardResult->cbResultCard[cbResultCount],tmpSearchCardResult.cbResultCard[0],
                           sizeof(BYTE)*tmpSearchCardResult.cbCardCount[0] );
				cbResultCount++;
			}
			cbTmpCount = SearchTakeCardType( cbCardData,cbCardCount,0,3,2,&tmpSearchCardResult );
			if( cbTmpCount > 0 )
			{
				pSearchCardResult->cbCardCount[cbResultCount] = tmpSearchCardResult.cbCardCount[0];
				CopyMemory( pSearchCardResult->cbResultCard[cbResultCount],tmpSearchCardResult.cbResultCard[0],
                           sizeof(BYTE)*tmpSearchCardResult.cbCardCount[0] );
				cbResultCount++;
			}
			cbTmpCount = SearchLineCardType( cbCardData,cbCardCount,0,1,0,&tmpSearchCardResult );
			if( cbTmpCount > 0 )
			{
				pSearchCardResult->cbCardCount[cbResultCount] = tmpSearchCardResult.cbCardCount[0];
				CopyMemory( pSearchCardResult->cbResultCard[cbResultCount],tmpSearchCardResult.cbResultCard[0],
                           sizeof(BYTE)*tmpSearchCardResult.cbCardCount[0] );
				cbResultCount++;
			}
            
			cbTmpCount = SearchLineCardType( cbCardData,cbCardCount,0,2,0,&tmpSearchCardResult );
			if( cbTmpCount > 0 )
			{
				pSearchCardResult->cbCardCount[cbResultCount] = tmpSearchCardResult.cbCardCount[0];
				CopyMemory( pSearchCardResult->cbResultCard[cbResultCount],tmpSearchCardResult.cbResultCard[0],
                           sizeof(BYTE)*tmpSearchCardResult.cbCardCount[0] );
				cbResultCount++;
			}
            
			cbTmpCount = SearchLineCardType( cbCardData,cbCardCount,0,3,0,&tmpSearchCardResult );
			if( cbTmpCount > 0 )
			{
				pSearchCardResult->cbCardCount[cbResultCount] = tmpSearchCardResult.cbCardCount[0];
				CopyMemory( pSearchCardResult->cbResultCard[cbResultCount],tmpSearchCardResult.cbResultCard[0],
                           sizeof(BYTE)*tmpSearchCardResult.cbCardCount[0] );
				cbResultCount++;
			}
            
			cbTmpCount = SearchThreeTwoLine( cbCardData,cbCardCount,&tmpSearchCardResult );
			if( cbTmpCount > 0 )
			{
				pSearchCardResult->cbCardCount[cbResultCount] = tmpSearchCardResult.cbCardCount[0];
				CopyMemory( pSearchCardResult->cbResultCard[cbResultCount],tmpSearchCardResult.cbResultCard[0],
                           sizeof(BYTE)*tmpSearchCardResult.cbCardCount[0] );
				cbResultCount++;
			}
            
			if( cbSameCount != 4 )
			{
				cbTmpCount = SearchSameCard( cbCardData,cbCardCount,0,4,&tmpSearchCardResult );
				if( cbTmpCount > 0 )
				{
					pSearchCardResult->cbCardCount[cbResultCount] = tmpSearchCardResult.cbCardCount[0];
					CopyMemory( pSearchCardResult->cbResultCard[cbResultCount],tmpSearchCardResult.cbResultCard[0],
                               sizeof(BYTE)*tmpSearchCardResult.cbCardCount[0] );
					cbResultCount++;
				}
			}
            
			if ((cbCardCount>=2)&&(cbCardData[0]==0x4F)&&(cbCardData[1]==0x4E))
			{
				pSearchCardResult->cbCardCount[cbResultCount] = 2;
				pSearchCardResult->cbResultCard[cbResultCount][0] = cbCardData[0];
				pSearchCardResult->cbResultCard[cbResultCount][1] = cbCardData[1];
                
				cbResultCount++;
			}
            
			pSearchCardResult->cbSearchCount = cbResultCount;
			return cbResultCount;
		}
        case CT_SINGLE:
        case CT_DOUBLE:
        case CT_THREE:
		{
			BYTE cbReferCard=cbTurnCardData[0];
			BYTE cbSameCount = 1;
			if( cbTurnOutType == CT_DOUBLE ) cbSameCount = 2;
			else if( cbTurnOutType == CT_THREE ) cbSameCount = 3;
            
			cbResultCount = SearchSameCard( cbCardData,cbCardCount,cbReferCard,cbSameCount,pSearchCardResult );
            
			break;
		}
        case CT_SINGLE_LINE:
        case CT_DOUBLE_LINE:
        case CT_THREE_LINE:
		{
			BYTE cbBlockCount = 1;
			if( cbTurnOutType == CT_DOUBLE_LINE ) cbBlockCount = 2;
			else if( cbTurnOutType == CT_THREE_LINE ) cbBlockCount = 3;
            
			BYTE cbLineCount = cbTurnCardCount/cbBlockCount;
            
			cbResultCount = SearchLineCardType( cbCardData,cbCardCount,cbTurnCardData[0],cbBlockCount,cbLineCount,pSearchCardResult );
            
			break;
		}
        case CT_THREE_LINE_TAKE_ONE:
        case CT_THREE_LINE_TAKE_TWO:
		{
			if( cbCardCount < cbTurnCardCount ) break;
            
			if( cbTurnCardCount == 4 || cbTurnCardCount == 5 )
			{
				BYTE cbTakeCardCount = cbTurnOutType==CT_THREE_LINE_TAKE_ONE?1:2;
                
				cbResultCount = SearchTakeCardType( cbCardData,cbCardCount,cbTurnCardData[2],3,cbTakeCardCount,pSearchCardResult );
			}
			else
			{
				BYTE cbBlockCount = 3;
				BYTE cbLineCount = cbTurnCardCount/(cbTurnOutType==CT_THREE_LINE_TAKE_ONE?4:5);
				BYTE cbTakeCardCount = cbTurnOutType==CT_THREE_LINE_TAKE_ONE?1:2;
                
				BYTE cbTmpTurnCard[MAX_COUNT] = {};
				CopyMemory( cbTmpTurnCard,cbTurnCardData,sizeof(BYTE)*cbTurnCardCount );
				SortOutCardList( cbTmpTurnCard,cbTurnCardCount );
				cbResultCount = SearchLineCardType( cbCardData,cbCardCount,cbTmpTurnCard[0],cbBlockCount,cbLineCount,pSearchCardResult );
                
                bool bAllDistill = true;
				for( BYTE i = 0; i < cbResultCount; i++ )
				{
					BYTE cbResultIndex = cbResultCount-i-1;
                    
					BYTE cbTmpCardData[MAX_COUNT];
					BYTE cbTmpCardCount = cbCardCount;
                    
					CopyMemory( cbTmpCardData,cbCardData,sizeof(BYTE)*cbCardCount );
					cbTmpCardCount -= pSearchCardResult->cbCardCount[cbResultIndex];
                    
					tagAnalyseResult  TmpResult = {};
					AnalysebCardData( cbTmpCardData,cbTmpCardCount,TmpResult );
                    
					BYTE cbDistillCard[MAX_COUNT] = {};
					BYTE cbDistillCount = 0;
					for( BYTE j = cbTakeCardCount-1; j < sizeof(TmpResult.cbBlockCount); j++ )
					{
						if( TmpResult.cbBlockCount[j] > 0 )
						{
							if( j+1 == cbTakeCardCount && TmpResult.cbBlockCount[j] >= cbLineCount )
							{
								BYTE cbTmpBlockCount = TmpResult.cbBlockCount[j];
								CopyMemory( cbDistillCard,&TmpResult.cbCardData[j][(cbTmpBlockCount-cbLineCount)*(j+1)],
                                           sizeof(BYTE)*(j+1)*cbLineCount );
								cbDistillCount = (j+1)*cbLineCount;
								break;
							}
							else
							{
								for( BYTE k = 0; k < TmpResult.cbBlockCount[j]; k++ )
								{
									BYTE cbTmpBlockCount = TmpResult.cbBlockCount[j];
									CopyMemory( &cbDistillCard[cbDistillCount],&TmpResult.cbCardData[j][(cbTmpBlockCount-k-1)*(j+1)],
                                               sizeof(BYTE)*cbTakeCardCount );
									cbDistillCount += cbTakeCardCount;
                                    
									if( cbDistillCount == cbTakeCardCount*cbLineCount ) break;
								}
							}
						}
                        
						if( cbDistillCount == cbTakeCardCount*cbLineCount ) break;
					}
					
					if( cbDistillCount == cbTakeCardCount*cbLineCount )
					{
						BYTE cbCount = pSearchCardResult->cbCardCount[cbResultIndex];
						CopyMemory( &pSearchCardResult->cbResultCard[cbResultIndex][cbCount],cbDistillCard,
                                   sizeof(BYTE)*cbDistillCount );
						pSearchCardResult->cbCardCount[cbResultIndex] += cbDistillCount;
					}
					else
					{
						bAllDistill = false;
						pSearchCardResult->cbCardCount[cbResultIndex] = 0;
					}
				}
                
				if( !bAllDistill )
				{
					pSearchCardResult->cbSearchCount = cbResultCount;
					cbResultCount = 0;
					for( BYTE i = 0; i < pSearchCardResult->cbSearchCount; i++ )
					{
						if( pSearchCardResult->cbCardCount[i] != 0 )
						{
							tmpSearchCardResult.cbCardCount[cbResultCount] = pSearchCardResult->cbCardCount[i];
							CopyMemory( tmpSearchCardResult.cbResultCard[cbResultCount],pSearchCardResult->cbResultCard[i],
                                       sizeof(BYTE)*pSearchCardResult->cbCardCount[i] );
							cbResultCount++;
						}
					}
					tmpSearchCardResult.cbSearchCount = cbResultCount;
					CopyMemory( pSearchCardResult,&tmpSearchCardResult,sizeof(tagSearchCardResult) );
				}
			}
            
			break;
		}
        case CT_FOUR_LINE_TAKE_ONE:
        case CT_FOUR_LINE_TAKE_TWO:
		{
			BYTE cbTakeCount = cbTurnOutType==CT_FOUR_LINE_TAKE_ONE?1:2;
            
			BYTE cbTmpTurnCard[MAX_COUNT] = {};
			CopyMemory( cbTmpTurnCard,cbTurnCardData,sizeof(BYTE)*cbTurnCardCount );
			SortOutCardList( cbTmpTurnCard,cbTurnCardCount );
            
			cbResultCount = SearchTakeCardType( cbCardData,cbCardCount,cbTmpTurnCard[0],4,cbTakeCount,pSearchCardResult );
            
			break;
		}
	}
    
	if ((cbCardCount>=4)&&(cbTurnOutType!=CT_MISSILE_CARD))
	{
		BYTE cbReferCard = 0;
		if (cbTurnOutType==CT_BOMB_CARD) cbReferCard=cbTurnCardData[0];
        
		BYTE cbTmpResultCount = SearchSameCard( cbCardData,cbCardCount,cbReferCard,4,&tmpSearchCardResult );
		for( BYTE i = 0; i < cbTmpResultCount; i++ )
		{
			pSearchCardResult->cbCardCount[cbResultCount] = tmpSearchCardResult.cbCardCount[i];
			CopyMemory( pSearchCardResult->cbResultCard[cbResultCount],tmpSearchCardResult.cbResultCard[i],
                       sizeof(BYTE)*tmpSearchCardResult.cbCardCount[i] );
			cbResultCount++;
		}
	}
    
	if (cbTurnOutType!=CT_MISSILE_CARD&&(cbCardCount>=2)&&(cbCardData[0]==0x4F)&&(cbCardData[1]==0x4E))
	{
		pSearchCardResult->cbCardCount[cbResultCount] = 2;
		pSearchCardResult->cbResultCard[cbResultCount][0] = cbCardData[0];
		pSearchCardResult->cbResultCard[cbResultCount][1] = cbCardData[1];
        
		cbResultCount++;
	}
    
	pSearchCardResult->cbSearchCount = cbResultCount;
	return cbResultCount;
}

void DDZCGameLogicSingle::GetAllBomCard(BYTE const cbHandCardData[], BYTE const cbHandCardCount, BYTE cbBomCardData[], BYTE &cbBomCardCount)
{
	BYTE cbTmpCardData[MAX_COUNT] ;
	CopyMemory(cbTmpCardData, cbHandCardData, cbHandCardCount) ;
    
	SortCardList(cbTmpCardData, cbHandCardCount, ST_ORDER);
    
	cbBomCardCount = 0 ;
    
	if(cbHandCardCount<2) return ;
    
	if(0x4F==cbTmpCardData[0] && 0x4E==cbTmpCardData[1])
	{
		cbBomCardData[cbBomCardCount++] = cbTmpCardData[0] ;
		cbBomCardData[cbBomCardCount++] = cbTmpCardData[1] ;
	}
    
	for (BYTE i=0;i<cbHandCardCount;i++)
	{
		BYTE cbSameCount=1;
		BYTE cbLogicValue=GetCardLogicValue(cbTmpCardData[i]);
        
		for (BYTE j=i+1;j<cbHandCardCount;j++)
		{
			if (GetCardLogicValue(cbTmpCardData[j])!=cbLogicValue) break;
            
			cbSameCount++;
		}
        
		if(4==cbSameCount)
		{
			cbBomCardData[cbBomCardCount++] = cbTmpCardData[i] ;
			cbBomCardData[cbBomCardCount++] = cbTmpCardData[i+1] ;
			cbBomCardData[cbBomCardCount++] = cbTmpCardData[i+2] ;
			cbBomCardData[cbBomCardCount++] = cbTmpCardData[i+3] ;
		}
		i+=cbSameCount-1;
	}
}

void DDZCGameLogicSingle::GetAllLineCard(BYTE const cbHandCardData[], BYTE const cbHandCardCount, BYTE cbLineCardData[], BYTE &cbLineCardCount)
{
	BYTE cbTmpCard[MAX_COUNT] ;
	CopyMemory(cbTmpCard, cbHandCardData, cbHandCardCount) ;
	
	SortCardList(cbTmpCard, cbHandCardCount, ST_ORDER) ;
    
	cbLineCardCount = 0 ;
    
	if(cbHandCardCount<5) return ;
    
	BYTE cbFirstCard = 0 ;
	for(BYTE i=0 ; i<cbHandCardCount ; ++i)	if(GetCardLogicValue(cbTmpCard[i])<15)	{cbFirstCard = i ; break ;}
    
	BYTE cbSingleLineCard[12] ;
	BYTE cbSingleLineCount=0 ;
	BYTE cbLeftCardCount = cbHandCardCount ;
	bool bFindSingleLine = true ;
    
	while (cbLeftCardCount>=5 && bFindSingleLine)
	{
		cbSingleLineCount=1 ;
		bFindSingleLine = false ;
		BYTE cbLastCard = cbTmpCard[cbFirstCard] ;
		cbSingleLineCard[cbSingleLineCount-1] = cbTmpCard[cbFirstCard] ;
		for (BYTE i=cbFirstCard+1; i<cbLeftCardCount; i++)
		{
			BYTE cbCardData=cbTmpCard[i];
            
			if (1!=(GetCardLogicValue(cbLastCard)-GetCardLogicValue(cbCardData)) && GetCardValue(cbLastCard)!=GetCardValue(cbCardData))
			{
				cbLastCard = cbTmpCard[i] ;
				if(cbSingleLineCount<5)
				{
					cbSingleLineCount = 1 ;
					cbSingleLineCard[cbSingleLineCount-1] = cbTmpCard[i] ;
					continue ;
				}
				else break ;
			}
			else if(GetCardValue(cbLastCard)!=GetCardValue(cbCardData))
			{
				cbLastCard = cbCardData ;
				cbSingleLineCard[cbSingleLineCount] = cbCardData ;
				++cbSingleLineCount ;
			}
		}
        
		if(cbSingleLineCount>=5)
		{
			RemoveCard(cbSingleLineCard, cbSingleLineCount, cbTmpCard, cbLeftCardCount) ;
			memcpy(cbLineCardData+cbLineCardCount , cbSingleLineCard, sizeof(BYTE)*cbSingleLineCount) ;
			cbLineCardCount += cbSingleLineCount ;
			cbLeftCardCount -= cbSingleLineCount ;
			bFindSingleLine = true ;
		}
	}
}

void DDZCGameLogicSingle::GetAllThreeCard(BYTE const cbHandCardData[], BYTE const cbHandCardCount, BYTE m_bTCardData[], BYTE &cbThreeCardCount)
{
	BYTE cbTmpCardData[MAX_COUNT] ;
	CopyMemory(cbTmpCardData, cbHandCardData, cbHandCardCount) ;
    
	SortCardList(cbTmpCardData, cbHandCardCount, ST_ORDER);
    
	cbThreeCardCount = 0 ;
    
	for (BYTE i=0;i<cbHandCardCount;i++)
	{
		BYTE cbSameCount=1;
		BYTE cbLogicValue=GetCardLogicValue(cbTmpCardData[i]);
        
		for (BYTE j=i+1;j<cbHandCardCount;j++)
		{
			if (GetCardLogicValue(cbTmpCardData[j])!=cbLogicValue) break;
            
			cbSameCount++;
		}
        
		if(cbSameCount>=3)
		{
			m_bTCardData[cbThreeCardCount++] = cbTmpCardData[i] ;
			m_bTCardData[cbThreeCardCount++] = cbTmpCardData[i+1] ;
			m_bTCardData[cbThreeCardCount++] = cbTmpCardData[i+2] ;
		}
        
		i+=cbSameCount-1;
	}
}

void DDZCGameLogicSingle::GetAllDoubleCard(BYTE const cbHandCardData[], BYTE const cbHandCardCount, BYTE m_bDCardData[], BYTE &cbDoubleCardCount)
{
	BYTE cbTmpCardData[MAX_COUNT] ;
	CopyMemory(cbTmpCardData, cbHandCardData, cbHandCardCount) ;
    
	SortCardList(cbTmpCardData, cbHandCardCount, ST_ORDER);
    
	cbDoubleCardCount = 0 ;
    
	for (BYTE i=0;i<cbHandCardCount;i++)
	{
		BYTE cbSameCount=1;
		BYTE cbLogicValue=GetCardLogicValue(cbTmpCardData[i]);
        
		for (BYTE j=i+1;j<cbHandCardCount;j++)
		{
			if (GetCardLogicValue(cbTmpCardData[j])!=cbLogicValue) break;
            
			cbSameCount++;
		}
        
		if(cbSameCount>=2)
		{
			m_bDCardData[cbDoubleCardCount++] = cbTmpCardData[i] ;
			m_bDCardData[cbDoubleCardCount++] = cbTmpCardData[i+1] ;
		}
        
		i+=cbSameCount-1;
	}
}

void DDZCGameLogicSingle::GetAllSingleCard(BYTE const cbHandCardData[], BYTE const cbHandCardCount, BYTE cbSingleCardData[], BYTE &cbSingleCardCount)
{
	cbSingleCardCount =0 ;
    
	BYTE cbTmpCardData[MAX_COUNT] ;
	CopyMemory(cbTmpCardData, cbHandCardData, cbHandCardCount) ;
    
	SortCardList(cbTmpCardData, cbHandCardCount, ST_ORDER);
    
	for (BYTE i=0;i<cbHandCardCount;i++)
	{
		BYTE cbSameCount=1;
		BYTE cbLogicValue=GetCardLogicValue(cbTmpCardData[i]);
        
		for (BYTE j=i+1;j<cbHandCardCount;j++)
		{
			if (GetCardLogicValue(cbTmpCardData[j])!=cbLogicValue) break;
            
			cbSameCount++;
		}
        
		if(cbSameCount==1)
		{
			cbSingleCardData[cbSingleCardCount++] = cbTmpCardData[i] ;
		}
        
		i+=cbSameCount-1;
	}
}


bool DDZCGameLogicSingle::AndroidOutCard(const BYTE cbHandCardData[], BYTE cbHandCardCount, const BYTE cbTurnCardData[], BYTE cbTurnCardCount, WORD wOutCardUser, WORD wMeChairID, tagOutCardResult & OutCardResult)
{
	
    WORD wUndersideOfBanker = (m_wBankerUser+1)%GAME_PLAYER ;	//ﾵ￘ￖ￷ￏￂﾼￒ
	WORD wUpsideOfBanker = (wUndersideOfBanker+1)%GAME_PLAYER ;	//ﾵ￘ￖ￷￉ￏﾼￒ
    
	ZeroMemory(&OutCardResult, sizeof(OutCardResult)) ;
    
	if(cbTurnCardCount==0)
	{
		if(wMeChairID==m_wBankerUser) BankerOutCard(cbHandCardData, cbHandCardCount, OutCardResult) ;
		else if(wMeChairID==wUndersideOfBanker) UndersideOfBankerOutCard(cbHandCardData, cbHandCardCount,wMeChairID,  OutCardResult) ;
        else if(wMeChairID==wUpsideOfBanker) UpsideOfBankerOutCard(cbHandCardData, cbHandCardCount, wMeChairID, OutCardResult) ;
        
	}
    else
	{
		if(wMeChairID==m_wBankerUser) BankerOutCard(cbHandCardData, cbHandCardCount, wOutCardUser, cbTurnCardData, cbTurnCardCount, OutCardResult) ;
		else if(wMeChairID==wUndersideOfBanker) UndersideOfBankerOutCard(cbHandCardData, cbHandCardCount, wOutCardUser, cbTurnCardData, cbTurnCardCount, OutCardResult) ;
		
		else if(wMeChairID==wUpsideOfBanker) UpsideOfBankerOutCard(cbHandCardData, cbHandCardCount, wOutCardUser, cbTurnCardData, cbTurnCardCount, OutCardResult) ;
        
		printf("OutCardResult.cbCardCount=%d \n",OutCardResult.cbCardCount);
		
		if (GetCardType(m_cbAllCardData[wOutCardUser], m_cbUserCardCount[wOutCardUser]) != CT_ERROR && m_lBankerOutCardCount == 1 && (OutCardResult.cbCardCount <= 0 ||
                                                                                                                                      !CompareCard(cbTurnCardData, OutCardResult.cbResultCard , cbTurnCardCount , OutCardResult.cbCardCount)))
		{
			tagOutCardTypeResult CardTypeResult[12+1] ;
			ZeroMemory(CardTypeResult, sizeof(CardTypeResult)) ;
            
			AnalyseOutCardType(cbHandCardData,cbHandCardCount,cbTurnCardData,cbTurnCardCount, CardTypeResult) ;
            
			BYTE cbOutCardType = GetCardType(cbTurnCardData, cbTurnCardCount) ;
            
			if (CardTypeResult[cbOutCardType].cbCardTypeCount > 0 && cbOutCardType != CT_THREE)
			{
				BYTE cbIndex = CardTypeResult[cbOutCardType].cbCardTypeCount - 1 ;
				BYTE cbCardCount = CardTypeResult[cbOutCardType].cbEachHandCardCount[cbIndex] ;
                
				CopyMemory(OutCardResult.cbResultCard, CardTypeResult[cbOutCardType].cbCardData[cbIndex], cbCardCount) ;
				OutCardResult.cbCardCount = cbCardCount ;
			}
            
			else if (CardTypeResult[CT_BOMB_CARD].cbCardTypeCount > 0)
			{
				BYTE cbIndex = CardTypeResult[CT_BOMB_CARD].cbCardTypeCount - 1 ;
				BYTE cbCardCount = CardTypeResult[CT_BOMB_CARD].cbEachHandCardCount[cbIndex] ;
				CopyMemory(OutCardResult.cbResultCard, CardTypeResult[CT_BOMB_CARD].cbCardData[cbIndex], cbCardCount) ;
				OutCardResult.cbCardCount = cbCardCount ;
			}
			else if (CardTypeResult[CT_MISSILE_CARD].cbCardTypeCount > 0)
			{
				OutCardResult.cbCardCount = 2 ;
				OutCardResult.cbResultCard[0] = 0x4F ;
				OutCardResult.cbResultCard[1] = 0x4E ;
			}
		}
        
        
		if (GetCardType(m_cbAllCardData[m_wBankerUser], m_cbUserCardCount[m_wBankerUser]) != CT_ERROR && (OutCardResult.cbCardCount <= 0 ||
                                                                                                          !CompareCard(cbTurnCardData, OutCardResult.cbResultCard , cbTurnCardCount , OutCardResult.cbCardCount)) &&
			m_cbUserCardCount[(1 + m_wBankerUser) % GAME_PLAYER] == NORMAL_COUNT && m_cbUserCardCount[(2 + m_wBankerUser) % GAME_PLAYER] == NORMAL_COUNT)
		{
            
			tagOutCardTypeResult CardTypeResult[12+1] ;
			ZeroMemory(CardTypeResult, sizeof(CardTypeResult)) ;
            
			AnalyseOutCardType(cbHandCardData,cbHandCardCount,cbTurnCardData,cbTurnCardCount, CardTypeResult) ;
            
			BYTE cbOutCardType = GetCardType(cbTurnCardData, cbTurnCardCount) ;
            
			if (CardTypeResult[cbOutCardType].cbCardTypeCount > 0 && cbOutCardType != CT_THREE)
			{
				BYTE cbIndex = CardTypeResult[cbOutCardType].cbCardTypeCount - 1 ;
				BYTE cbCardCount = CardTypeResult[cbOutCardType].cbEachHandCardCount[cbIndex] ;
                
				CopyMemory(OutCardResult.cbResultCard, CardTypeResult[cbOutCardType].cbCardData[cbIndex], cbCardCount) ;
				OutCardResult.cbCardCount = cbCardCount ;
			}
            
			else if (CardTypeResult[CT_BOMB_CARD].cbCardTypeCount > 0)
			{
				BYTE cbIndex = CardTypeResult[CT_BOMB_CARD].cbCardTypeCount - 1 ;
				BYTE cbCardCount = CardTypeResult[CT_BOMB_CARD].cbEachHandCardCount[cbIndex] ;
				CopyMemory(OutCardResult.cbResultCard, CardTypeResult[CT_BOMB_CARD].cbCardData[cbIndex], cbCardCount) ;
				OutCardResult.cbCardCount = cbCardCount ;
			}
			else if (CardTypeResult[CT_MISSILE_CARD].cbCardTypeCount > 0)
			{
				OutCardResult.cbCardCount = 2 ;
				OutCardResult.cbResultCard[0] = 0x4F ;
				OutCardResult.cbResultCard[1] = 0x4E ;
			}
		}
        
	}
    
    if (m_wBankerUser == wMeChairID && OutCardResult.cbCardCount > 0)
		++m_lBankerOutCardCount ;
    
	return true ;
}


BYTE DDZCGameLogicSingle::SearchSameCard( const BYTE cbHandCardData[], BYTE cbHandCardCount, BYTE cbReferCard, BYTE cbSameCardCount,
                                         tagSearchCardResult *pSearchCardResult )
{
	if( pSearchCardResult )
		ZeroMemory(pSearchCardResult,sizeof(tagSearchCardResult));
	BYTE cbResultCount = 0;
    
    BYTE cbCardData[MAX_COUNT];
	BYTE cbCardCount=cbHandCardCount;
	CopyMemory(cbCardData,cbHandCardData,sizeof(BYTE)*cbHandCardCount);
    
	SortCardList(cbCardData,cbCardCount,ST_ORDER);
    
	tagAnalyseResult AnalyseResult = {};
	AnalysebCardData( cbCardData,cbCardCount,AnalyseResult );
	
	BYTE cbReferLogicValue = cbReferCard==0?0:GetCardLogicValue(cbReferCard);
	BYTE cbBlockIndex = cbSameCardCount-1;
	do
	{
		for( BYTE i = 0; i < AnalyseResult.cbBlockCount[cbBlockIndex]; i++ )
		{
			BYTE cbIndex = (AnalyseResult.cbBlockCount[cbBlockIndex]-i-1)*(cbBlockIndex+1);
			if( GetCardLogicValue(AnalyseResult.cbCardData[cbBlockIndex][cbIndex]) > cbReferLogicValue )
			{
				if( pSearchCardResult == NULL ) return 1;
                
				CopyMemory( pSearchCardResult->cbResultCard[cbResultCount],&AnalyseResult.cbCardData[cbBlockIndex][cbIndex],
                           cbSameCardCount*sizeof(BYTE) );
				pSearchCardResult->cbCardCount[cbResultCount] = cbSameCardCount;
                
				cbResultCount++;
			}
		}
        
		cbBlockIndex++;
	}while( cbBlockIndex < sizeof(AnalyseResult.cbBlockCount) );
    
	if( pSearchCardResult )
		pSearchCardResult->cbSearchCount = cbResultCount;
	return cbResultCount;
}


BYTE DDZCGameLogicSingle::SearchTakeCardType( const BYTE cbHandCardData[], BYTE cbHandCardCount, BYTE cbReferCard, BYTE cbSameCount, BYTE cbTakeCardCount,
                                             tagSearchCardResult *pSearchCardResult )
{
	if( pSearchCardResult )
		ZeroMemory(pSearchCardResult,sizeof(tagSearchCardResult));
	BYTE cbResultCount = 0;
    
	if( cbSameCount != 3 && cbSameCount != 4 )
		return cbResultCount;
	if( cbTakeCardCount != 1 && cbTakeCardCount != 2 )
		return cbResultCount;
    
	if( cbSameCount == 4 && cbHandCardCount<cbSameCount+cbTakeCardCount*2 ||
       cbHandCardCount < cbSameCount+cbTakeCardCount )
		return cbResultCount;
	BYTE cbCardData[MAX_COUNT];
	BYTE cbCardCount=cbHandCardCount;
	CopyMemory(cbCardData,cbHandCardData,sizeof(BYTE)*cbHandCardCount);
    
	SortCardList(cbCardData,cbCardCount,ST_ORDER);
    
	tagSearchCardResult SameCardResult = {};
	BYTE cbSameCardResultCount = SearchSameCard( cbCardData,cbCardCount,cbReferCard,cbSameCount,&SameCardResult );
    
	if( cbSameCardResultCount > 0 )
	{
		tagAnalyseResult AnalyseResult;
		AnalysebCardData(cbCardData,cbCardCount,AnalyseResult);
        
		BYTE cbNeedCount = cbSameCount+cbTakeCardCount;
		if( cbSameCount == 4 ) cbNeedCount += cbTakeCardCount;
        
		for( BYTE i = 0; i < cbSameCardResultCount; i++ )
		{
			bool bMerge = false;
            
			for( BYTE j = cbTakeCardCount-1; j < sizeof(AnalyseResult.cbBlockCount); j++ )
			{
				for( BYTE k = 0; k < AnalyseResult.cbBlockCount[j]; k++ )
				{
					BYTE cbIndex = (AnalyseResult.cbBlockCount[j]-k-1)*(j+1);
                    
                    if( GetCardValue(SameCardResult.cbResultCard[i][0]) ==
                       GetCardValue(AnalyseResult.cbCardData[j][cbIndex]) )
						continue;
                    
					BYTE cbCount = SameCardResult.cbCardCount[i];
					CopyMemory( &SameCardResult.cbResultCard[i][cbCount],&AnalyseResult.cbCardData[j][cbIndex],
                               sizeof(BYTE)*cbTakeCardCount );
					SameCardResult.cbCardCount[i] += cbTakeCardCount;
                    
					if( SameCardResult.cbCardCount[i] < cbNeedCount ) continue;
                    
					if( pSearchCardResult == NULL ) return 1;
                    
					CopyMemory( pSearchCardResult->cbResultCard[cbResultCount],SameCardResult.cbResultCard[i],
                               sizeof(BYTE)*SameCardResult.cbCardCount[i] );
					pSearchCardResult->cbCardCount[cbResultCount] = SameCardResult.cbCardCount[i];
					cbResultCount++;
                    
					bMerge = true;
                    
					break;
				}
                
				if( bMerge ) break;
			}
		}
	}
    
	if( pSearchCardResult )
		pSearchCardResult->cbSearchCount = cbResultCount;
	return cbResultCount;
}

BYTE DDZCGameLogicSingle::SearchLineCardType( const BYTE cbHandCardData[], BYTE cbHandCardCount, BYTE cbReferCard, BYTE cbBlockCount, BYTE cbLineCount,
                                             tagSearchCardResult *pSearchCardResult )
{
    
	if( pSearchCardResult )
		ZeroMemory(pSearchCardResult,sizeof(tagSearchCardResult));
	BYTE cbResultCount = 0;
    
	BYTE cbLessLineCount = 0;
	if( cbLineCount == 0 )
	{
		if( cbBlockCount == 1 )
			cbLessLineCount = 5;
		else if( cbBlockCount == 2 )
			cbLessLineCount = 3;
		else cbLessLineCount = 2;
	}
	else cbLessLineCount = cbLineCount;
    
	BYTE cbReferIndex = 2;
	if( cbReferCard != 0 )
	{
		cbReferIndex = GetCardLogicValue(cbReferCard)-cbLessLineCount+1;
	}
	if( cbReferIndex+cbLessLineCount > 14 ) return cbResultCount;
    
	if( cbHandCardCount < cbLessLineCount*cbBlockCount ) return cbResultCount;
    
	BYTE cbCardData[MAX_COUNT];
	BYTE cbCardCount=cbHandCardCount;
	CopyMemory(cbCardData,cbHandCardData,sizeof(BYTE)*cbHandCardCount);
    
	SortCardList(cbCardData,cbCardCount,ST_ORDER);
    
	tagDistributing Distributing = {};
	AnalysebDistributing(cbCardData,cbCardCount,Distributing);
    
	BYTE cbTmpLinkCount = 0;
	BYTE cbValueIndex;
	for (cbValueIndex=cbReferIndex;cbValueIndex<13;cbValueIndex++)
	{
		if ( Distributing.cbDistributing[cbValueIndex][cbIndexCount]<cbBlockCount )
		{
			if( cbTmpLinkCount < cbLessLineCount )
			{
				cbTmpLinkCount=0;
				continue;
			}
			else cbValueIndex--;
		}
		else
		{
			cbTmpLinkCount++;
			if( cbLineCount == 0 ) continue;
		}
        
		if( cbTmpLinkCount >= cbLessLineCount )
		{
			if( pSearchCardResult == NULL ) return 1;
            
			BYTE cbCount = 0;
			for( BYTE cbIndex = cbValueIndex+1-cbTmpLinkCount; cbIndex <= cbValueIndex; cbIndex++ )
			{
				BYTE cbTmpCount = 0;
				for (BYTE cbColorIndex=0;cbColorIndex<4;cbColorIndex++)
				{
					for( BYTE cbColorCount = 0; cbColorCount < Distributing.cbDistributing[cbIndex][3-cbColorIndex]; cbColorCount++ )
					{
						pSearchCardResult->cbResultCard[cbResultCount][cbCount++]=MakeCardData(cbIndex,3-cbColorIndex);
                        
						if( ++cbTmpCount == cbBlockCount ) break;
					}
					if( cbTmpCount == cbBlockCount ) break;
				}
			}
            
            pSearchCardResult->cbCardCount[cbResultCount] = cbCount;
			cbResultCount++;
            
			if( cbLineCount != 0 )
			{
				cbTmpLinkCount--;
			}
			else
			{
				cbTmpLinkCount = 0;
			}
		}
	}
    
	if( cbTmpLinkCount >= cbLessLineCount-1 && cbValueIndex == 13 )
	{
		if( Distributing.cbDistributing[0][cbIndexCount] >= cbBlockCount ||
           cbTmpLinkCount >= cbLessLineCount )
		{
			if( pSearchCardResult == NULL ) return 1;
            
			BYTE cbCount = 0;
			BYTE cbTmpCount = 0;
			for( BYTE cbIndex = cbValueIndex-cbTmpLinkCount; cbIndex < 13; cbIndex++ )
			{
				cbTmpCount = 0;
				for (BYTE cbColorIndex=0;cbColorIndex<4;cbColorIndex++)
				{
					for( BYTE cbColorCount = 0; cbColorCount < Distributing.cbDistributing[cbIndex][3-cbColorIndex]; cbColorCount++ )
					{
						pSearchCardResult->cbResultCard[cbResultCount][cbCount++]=MakeCardData(cbIndex,3-cbColorIndex);
                        
						if( ++cbTmpCount == cbBlockCount ) break;
					}
					if( cbTmpCount == cbBlockCount ) break;
				}
			}
			if( Distributing.cbDistributing[0][cbIndexCount] >= cbBlockCount )
			{
				cbTmpCount = 0;
				for (BYTE cbColorIndex=0;cbColorIndex<4;cbColorIndex++)
				{
					for( BYTE cbColorCount = 0; cbColorCount < Distributing.cbDistributing[0][3-cbColorIndex]; cbColorCount++ )
					{
						pSearchCardResult->cbResultCard[cbResultCount][cbCount++]=MakeCardData(0,3-cbColorIndex);
                        
						if( ++cbTmpCount == cbBlockCount ) break;
					}
					if( cbTmpCount == cbBlockCount ) break;
				}
			}
            
 			pSearchCardResult->cbCardCount[cbResultCount] = cbCount;
			cbResultCount++;
		}
	}
    
	if( pSearchCardResult )
		pSearchCardResult->cbSearchCount = cbResultCount;
	return cbResultCount;
}

BYTE DDZCGameLogicSingle::SearchThreeTwoLine( const BYTE cbHandCardData[], BYTE cbHandCardCount, tagSearchCardResult *pSearchCardResult )
{
	if( pSearchCardResult )
		ZeroMemory(pSearchCardResult,sizeof(tagSearchCardResult));
    
	tagSearchCardResult tmpSearchResult = {};
	tagSearchCardResult tmpSingleWing = {};
	tagSearchCardResult tmpDoubleWing = {};
	BYTE cbTmpResultCount = 0;
    
	cbTmpResultCount = SearchLineCardType( cbHandCardData,cbHandCardCount,0,3,0,&tmpSearchResult );
    
	if( cbTmpResultCount > 0 )
	{
		for( BYTE i = 0; i < cbTmpResultCount; i++ )
		{
			BYTE cbTmpCardData[MAX_COUNT];
			BYTE cbTmpCardCount = cbHandCardCount;
            
			if( cbHandCardCount-tmpSearchResult.cbCardCount[i] < tmpSearchResult.cbCardCount[i]/3 )
			{
				BYTE cbNeedDelCount = 3;
				while( cbHandCardCount+cbNeedDelCount-tmpSearchResult.cbCardCount[i] < (tmpSearchResult.cbCardCount[i]-cbNeedDelCount)/3 )
					cbNeedDelCount += 3;
				
                if( (tmpSearchResult.cbCardCount[i]-cbNeedDelCount)/3 < 2 )
				{
					continue;
				}
                
				RemoveCard( tmpSearchResult.cbResultCard[i],cbNeedDelCount,tmpSearchResult.cbResultCard[i],
                           tmpSearchResult.cbCardCount[i] );
				tmpSearchResult.cbCardCount[i] -= cbNeedDelCount;
			}
            
			if( pSearchCardResult == NULL ) return 1;
            
			CopyMemory( cbTmpCardData,cbHandCardData,sizeof(BYTE)*cbHandCardCount );
			cbTmpCardCount -= tmpSearchResult.cbCardCount[i];
            
			BYTE cbNeedCount = tmpSearchResult.cbCardCount[i]/3;
            
			BYTE cbResultCount = tmpSingleWing.cbSearchCount++;
			CopyMemory( tmpSingleWing.cbResultCard[cbResultCount],tmpSearchResult.cbResultCard[i],
                       sizeof(BYTE)*tmpSearchResult.cbCardCount[i] );
			CopyMemory( &tmpSingleWing.cbResultCard[cbResultCount][tmpSearchResult.cbCardCount[i]],
                       &cbTmpCardData[cbTmpCardCount-cbNeedCount],sizeof(BYTE)*cbNeedCount );
			tmpSingleWing.cbCardCount[i] = tmpSearchResult.cbCardCount[i]+cbNeedCount;
            
			if( cbTmpCardCount < tmpSearchResult.cbCardCount[i]/3*2 )
			{
				BYTE cbNeedDelCount = 3;
				while( cbTmpCardCount+cbNeedDelCount-tmpSearchResult.cbCardCount[i] < (tmpSearchResult.cbCardCount[i]-cbNeedDelCount)/3*2 )
					cbNeedDelCount += 3;
				if( (tmpSearchResult.cbCardCount[i]-cbNeedDelCount)/3 < 2 )
				{
					continue;
				}
                
				RemoveCard( tmpSearchResult.cbResultCard[i],cbNeedDelCount,tmpSearchResult.cbResultCard[i],
                           tmpSearchResult.cbCardCount[i] );
				tmpSearchResult.cbCardCount[i] -= cbNeedDelCount;
                
				CopyMemory( cbTmpCardData,cbHandCardData,sizeof(BYTE)*cbHandCardCount );
				cbTmpCardCount = cbHandCardCount-tmpSearchResult.cbCardCount[i];
			}
            tagAnalyseResult  TmpResult = {};
			AnalysebCardData( cbTmpCardData,cbTmpCardCount,TmpResult );
            
			BYTE cbDistillCard[MAX_COUNT] = {};
			BYTE cbDistillCount = 0;
			BYTE cbLineCount = tmpSearchResult.cbCardCount[i]/3;
			for( BYTE j = 1; j < sizeof(TmpResult.cbBlockCount); j++ )
			{
				if( TmpResult.cbBlockCount[j] > 0 )
				{
					if( j+1 == 2 && TmpResult.cbBlockCount[j] >= cbLineCount )
					{
						BYTE cbTmpBlockCount = TmpResult.cbBlockCount[j];
						CopyMemory( cbDistillCard,&TmpResult.cbCardData[j][(cbTmpBlockCount-cbLineCount)*(j+1)],
                                   sizeof(BYTE)*(j+1)*cbLineCount );
						cbDistillCount = (j+1)*cbLineCount;
						break;
					}
					else
					{
						for( BYTE k = 0; k < TmpResult.cbBlockCount[j]; k++ )
						{
							BYTE cbTmpBlockCount = TmpResult.cbBlockCount[j];
							CopyMemory( &cbDistillCard[cbDistillCount],&TmpResult.cbCardData[j][(cbTmpBlockCount-k-1)*(j+1)],
                                       sizeof(BYTE)*2 );
							cbDistillCount += 2;
                            
							if( cbDistillCount == 2*cbLineCount ) break;
						}
					}
				}
                
				if( cbDistillCount == 2*cbLineCount ) break;
			}
            
			if( cbDistillCount == 2*cbLineCount )
			{
				cbResultCount = tmpDoubleWing.cbSearchCount++;
				CopyMemory( tmpDoubleWing.cbResultCard[cbResultCount],tmpSearchResult.cbResultCard[i],
                           sizeof(BYTE)*tmpSearchResult.cbCardCount[i] );
				CopyMemory( &tmpDoubleWing.cbResultCard[cbResultCount][tmpSearchResult.cbCardCount[i]],
                           cbDistillCard,sizeof(BYTE)*cbDistillCount );
				tmpDoubleWing.cbCardCount[i] = tmpSearchResult.cbCardCount[i]+cbDistillCount;
			}
		}
        
		for( BYTE i = 0; i < tmpDoubleWing.cbSearchCount; i++ )
		{
			BYTE cbResultCount = pSearchCardResult->cbSearchCount++;
            
			CopyMemory( pSearchCardResult->cbResultCard[cbResultCount],tmpDoubleWing.cbResultCard[i],
                       sizeof(BYTE)*tmpDoubleWing.cbCardCount[i] );
			pSearchCardResult->cbCardCount[cbResultCount] = tmpDoubleWing.cbCardCount[i];
		}
		for( BYTE i = 0; i < tmpSingleWing.cbSearchCount; i++ )
		{
			BYTE cbResultCount = pSearchCardResult->cbSearchCount++;
            
			CopyMemory( pSearchCardResult->cbResultCard[cbResultCount],tmpSingleWing.cbResultCard[i],
                       sizeof(BYTE)*tmpSingleWing.cbCardCount[i] );
			pSearchCardResult->cbCardCount[cbResultCount] = tmpSingleWing.cbCardCount[i];
		}
	}
    
	return pSearchCardResult==NULL?0:pSearchCardResult->cbSearchCount;
}




void DDZCGameLogicSingle::AnalyseOutCardType(BYTE const cbHandCardData[], BYTE const cbHandCardCount, BYTE const cbTurnCardData[], BYTE const cbTurnCardCount,tagOutCardTypeResult CardTypeResult[12+1])
{
	ZeroMemory(CardTypeResult, sizeof(CardTypeResult[0])*12) ;
    
	BYTE cbTmpCard[MAX_COUNT];
	CopyMemory(cbTmpCard, cbHandCardData, cbHandCardCount) ;
	SortCardList(cbTmpCard, cbHandCardCount, ST_ORDER) ;
	//	SortCardList(cbTurnCardData, cbTurnCardCount, ST_ORDER) ;
    
	BYTE cbTurnCardType = GetCardType(cbTurnCardData, cbTurnCardCount) ;
#ifdef	_DEBUG
	if(cbTurnCardType==CT_ERROR)
	{
		CString str = "\nAnalyseOutCardType:  ";
		for(BYTE i=0; i<cbTurnCardCount; ++i)
		{
			CString strTmp ;
			strTmp.Format("%d,", GetCardValue(cbTurnCardData[i])) ;
			str += strTmp ;
		}
		str += "\n\n" ;
		OutputDebugString(str) ;
	}
#endif
	if(cbTurnCardType==CT_ERROR)
		return ;
    
	if(cbTurnCardType!=CT_MISSILE_CARD && cbTurnCardType!=CT_BOMB_CARD)
	{
		if(cbHandCardCount>=2 && 0x4F==cbTmpCard[0] && 0x4E==cbTmpCard[1])
		{
			BYTE Index = CardTypeResult[CT_BOMB_CARD].cbCardTypeCount;
			CardTypeResult[CT_BOMB_CARD].cbCardType = CT_BOMB_CARD ;
			CardTypeResult[CT_BOMB_CARD].cbCardData[Index][0] = cbTmpCard[0] ;
			CardTypeResult[CT_BOMB_CARD].cbCardData[Index][1] = cbTmpCard[1] ;
			CardTypeResult[CT_BOMB_CARD].cbEachHandCardCount[Index] = 2 ;
			CardTypeResult[CT_BOMB_CARD].cbCardTypeCount++;
            
			BYTE cbBomCardData[MAX_COUNT];
			BYTE cbBomCardCount=0;
			GetAllBomCard(cbTmpCard+2, cbHandCardCount-2, cbBomCardData, cbBomCardCount) ;
			for(BYTE i=0; i<cbBomCardCount/4; ++i)
			{
				Index = CardTypeResult[CT_BOMB_CARD].cbCardTypeCount;
				CardTypeResult[CT_BOMB_CARD].cbCardType = CT_BOMB_CARD ;
				CopyMemory(CardTypeResult[CT_BOMB_CARD].cbCardData[Index], cbBomCardData+4*i, 4) ;
				CardTypeResult[CT_BOMB_CARD].cbEachHandCardCount[Index] = 4;
				CardTypeResult[CT_BOMB_CARD].cbCardTypeCount++;
                
			}
		}
		else
		{
			BYTE cbBomCardData[MAX_COUNT];
			BYTE cbBomCardCount=0;
			GetAllBomCard(cbTmpCard, cbHandCardCount, cbBomCardData, cbBomCardCount) ;
			for(BYTE i=0; i<cbBomCardCount/4; ++i)
			{
				BYTE Index = CardTypeResult[CT_BOMB_CARD].cbCardTypeCount;
				CardTypeResult[CT_BOMB_CARD].cbCardType = CT_BOMB_CARD ;
				CopyMemory(CardTypeResult[CT_BOMB_CARD].cbCardData[Index], cbBomCardData+4*i, 4) ;
				CardTypeResult[CT_BOMB_CARD].cbEachHandCardCount[Index] = 4;
				CardTypeResult[CT_BOMB_CARD].cbCardTypeCount++;
			}
		}
	}
    
	switch(cbTurnCardType)
	{
        case CT_SINGLE:
		{
			for(BYTE i=0; i<cbHandCardCount; ++i)
				if(GetCardLogicValue(cbTmpCard[i])>GetCardLogicValue(cbTurnCardData[0]))
				{
					BYTE Index = CardTypeResult[CT_SINGLE].cbCardTypeCount ;
					CardTypeResult[CT_SINGLE].cbCardType = CT_SINGLE ;
					CardTypeResult[CT_SINGLE].cbCardData[Index][0] = cbTmpCard[i];
					CardTypeResult[CT_SINGLE].cbEachHandCardCount[Index] = 1;
					CardTypeResult[CT_SINGLE].cbCardTypeCount++ ;
				}
            break ;
		}
        case CT_DOUBLE:
		{
			
			for (BYTE i=0;i<cbHandCardCount;i++)
			{
				BYTE cbSameCount=1;
				BYTE cbLogicValue=GetCardLogicValue(cbTmpCard[i]);
                
				for (BYTE j=i+1;j<cbHandCardCount;j++)
				{
					if (GetCardLogicValue(cbTmpCard[j])!=cbLogicValue) break;
                    
					cbSameCount++;
				}
                
				if(cbSameCount>=2 && GetCardLogicValue(cbTmpCard[i])>GetCardLogicValue(cbTurnCardData[0]))
				{
					BYTE Index = CardTypeResult[CT_DOUBLE].cbCardTypeCount ;
					CardTypeResult[CT_DOUBLE].cbCardType = CT_DOUBLE ;
					CardTypeResult[CT_DOUBLE].cbCardData[Index][0] = cbTmpCard[i];
					CardTypeResult[CT_DOUBLE].cbCardData[Index][1] = cbTmpCard[i+1];
					CardTypeResult[CT_DOUBLE].cbEachHandCardCount[Index] = 2;
					CardTypeResult[CT_DOUBLE].cbCardTypeCount++ ;
				}
				i+=cbSameCount-1;
			}
			break ;
		}
        case CT_THREE:
		{
            
			for (BYTE i=0;i<cbHandCardCount;i++)
			{
				BYTE cbSameCount=1;
				BYTE cbLogicValue=GetCardLogicValue(cbTmpCard[i]);
                
				for (BYTE j=i+1;j<cbHandCardCount;j++)
				{
					if (GetCardLogicValue(cbTmpCard[j])!=cbLogicValue) break;
                    
					cbSameCount++;
				}
                
				if(cbSameCount>=3 && GetCardLogicValue(cbTmpCard[i])>GetCardLogicValue(cbTurnCardData[0]))
				{
					BYTE Index = CardTypeResult[CT_THREE].cbCardTypeCount ;
					CardTypeResult[CT_THREE].cbCardType = CT_THREE ;
					CardTypeResult[CT_THREE].cbCardData[Index][0] = cbTmpCard[i];
					CardTypeResult[CT_THREE].cbCardData[Index][1] = cbTmpCard[i+1];
					CardTypeResult[CT_THREE].cbCardData[Index][2] = cbTmpCard[i+2];
					CardTypeResult[CT_THREE].cbEachHandCardCount[Index] = 3;
					CardTypeResult[CT_THREE].cbCardTypeCount++ ;
				}
				i+=cbSameCount-1;
			}
			break ;
		}
        case CT_SINGLE_LINE:
		{
			BYTE cbFirstCard = 0 ;
			for(BYTE i=0 ; i<cbHandCardCount ; ++i)	if(GetCardLogicValue(cbTmpCard[i])<15)	{cbFirstCard = i ; break ;}
            
			BYTE cbSingleLineCard[12] ;
			BYTE cbSingleLineCount=1 ;
			BYTE cbLeftCardCount = cbHandCardCount ;
			bool bFindSingleLine = true ;
            
			while (cbLeftCardCount>=cbTurnCardCount && bFindSingleLine)
			{
				cbSingleLineCount=1 ;
				bFindSingleLine = false ;
				BYTE cbLastCard = cbTmpCard[cbFirstCard] ;
				cbSingleLineCard[cbSingleLineCount-1] = cbTmpCard[cbFirstCard] ;
				for (BYTE i=cbFirstCard+1; i<cbLeftCardCount; i++)
				{
					BYTE cbCardData=cbTmpCard[i];
                    
					if (1!=(GetCardLogicValue(cbLastCard)-GetCardLogicValue(cbCardData)) && GetCardValue(cbLastCard)!=GetCardValue(cbCardData))
					{
						cbLastCard = cbTmpCard[i] ;
                        
						if(cbSingleLineCount<cbTurnCardCount)
						{
							cbSingleLineCount = 1 ;
							cbSingleLineCard[cbSingleLineCount-1] = cbTmpCard[i] ;
							continue ;
						}
						else break ;
					}
					else if(GetCardValue(cbLastCard)!=GetCardValue(cbCardData))
					{
						cbLastCard = cbCardData ;
						cbSingleLineCard[cbSingleLineCount] = cbCardData ;
						++cbSingleLineCount ;
					}
				}
                
				if(cbSingleLineCount>=cbTurnCardCount && GetCardLogicValue(cbSingleLineCard[0])>GetCardLogicValue(cbTurnCardData[0]))
				{
					BYTE Index ;
					BYTE cbStart=0 ;
					while (GetCardLogicValue(cbSingleLineCard[cbStart])>GetCardLogicValue(cbTurnCardData[0]) && ((cbSingleLineCount-cbStart)>=cbTurnCardCount))
					{
						Index = CardTypeResult[CT_SINGLE_LINE].cbCardTypeCount ;
						CardTypeResult[CT_SINGLE_LINE].cbCardType = CT_SINGLE_LINE ;
						CopyMemory(CardTypeResult[CT_SINGLE_LINE].cbCardData[Index], cbSingleLineCard+cbStart, sizeof(BYTE)*cbTurnCardCount);
						CardTypeResult[CT_SINGLE_LINE].cbEachHandCardCount[Index] = cbTurnCardCount;
						CardTypeResult[CT_SINGLE_LINE].cbCardTypeCount++ ;
						cbStart++;
					}
                    
					RemoveCard(cbSingleLineCard, cbSingleLineCount, cbTmpCard, cbLeftCardCount) ;
					cbLeftCardCount -= cbSingleLineCount ;
					bFindSingleLine = true ;
				}
			}
            
			break ;
		}
        case CT_DOUBLE_LINE:
		{
			BYTE cbFirstCard = 0 ;
			for(BYTE i=0 ; i<cbHandCardCount ; ++i)	if(GetCardLogicValue(cbTmpCard[i])<15)	{cbFirstCard = i ; break ;}
            
			BYTE cbLeftCardCount = cbHandCardCount-cbFirstCard ;
			bool bFindDoubleLine = true ;
			BYTE cbDoubleLineCount = 0 ;
			BYTE cbDoubleLineCard[24] ;
			while (cbLeftCardCount>=cbTurnCardCount && bFindDoubleLine)
			{
				BYTE cbLastCard = cbTmpCard[cbFirstCard] ;
				BYTE cbSameCount = 1 ;
				cbDoubleLineCount = 0 ;
				bFindDoubleLine=false ;
				for(BYTE i=cbFirstCard+1 ; i<cbLeftCardCount+cbFirstCard ; ++i)
				{
					while (GetCardValue(cbLastCard)==GetCardValue(cbTmpCard[i]) && i<cbLeftCardCount+cbFirstCard)
					{
						++cbSameCount;
						++i ;
					}
                    
					BYTE cbLastDoubleCardValue ;
					if(cbDoubleLineCount>0) cbLastDoubleCardValue = GetCardLogicValue(cbDoubleLineCard[cbDoubleLineCount-1]) ;
                    
					if((cbSameCount<2 || (cbDoubleLineCount>0 && (cbLastDoubleCardValue-GetCardLogicValue(cbLastCard))!=1)) && i<=cbLeftCardCount+cbFirstCard)
					{
						if(cbDoubleLineCount>=cbTurnCardCount) break ;
                        
						if(cbSameCount>=2) i-=cbSameCount ;
                        
						cbLastCard = cbTmpCard[i] ;
						cbDoubleLineCount = 0 ;
					}
					else if(cbSameCount>=2)
					{
						cbDoubleLineCard[cbDoubleLineCount] = cbTmpCard[i-cbSameCount] ;
						cbDoubleLineCard[cbDoubleLineCount+1] = cbTmpCard[i-cbSameCount+1] ;
						cbDoubleLineCount += 2 ;
                        
						if(i==(cbLeftCardCount+cbFirstCard-2))
							if((GetCardLogicValue(cbLastCard)-GetCardLogicValue(cbTmpCard[i]))==1 && (GetCardLogicValue(cbTmpCard[i])==GetCardLogicValue(cbTmpCard[i+1])))
							{
								cbDoubleLineCard[cbDoubleLineCount] = cbTmpCard[i] ;
								cbDoubleLineCard[cbDoubleLineCount+1] = cbTmpCard[i+1] ;
								cbDoubleLineCount += 2 ;
								break ;
							}
                        
					}
                    
					cbLastCard = cbTmpCard[i] ;
					cbSameCount = 1 ;
				}
                
				if(cbDoubleLineCount>=cbTurnCardCount)
				{
					BYTE Index ;
					BYTE cbStart=0 ;
					while (GetCardLogicValue(cbDoubleLineCard[cbStart])>GetCardLogicValue(cbTurnCardData[0]) && ((cbDoubleLineCount-cbStart)>=cbTurnCardCount))
					{
						Index = CardTypeResult[CT_DOUBLE_LINE].cbCardTypeCount ;
						CardTypeResult[CT_DOUBLE_LINE].cbCardType = CT_DOUBLE_LINE ;
						CopyMemory(CardTypeResult[CT_DOUBLE_LINE].cbCardData[Index], cbDoubleLineCard+cbStart, sizeof(BYTE)*cbTurnCardCount);
						CardTypeResult[CT_DOUBLE_LINE].cbEachHandCardCount[Index] = cbTurnCardCount;
						CardTypeResult[CT_DOUBLE_LINE].cbCardTypeCount++ ;
						cbStart += 2;
					}
					RemoveCard(cbDoubleLineCard, cbDoubleLineCount, cbTmpCard, cbFirstCard+cbLeftCardCount) ;
					bFindDoubleLine=true ;
					cbLeftCardCount -= cbDoubleLineCount ;
				}
			}
            
			break;
		}
        case CT_THREE_LINE:
		{
			BYTE cbFirstCard = 0 ;
			for(BYTE i=0 ; i<cbHandCardCount ; ++i)	if(GetCardLogicValue(cbTmpCard[i])<15)	{cbFirstCard = i ; break ;}
            
			BYTE cbLeftCardCount = cbHandCardCount-cbFirstCard ;
			bool bFindThreeLine = true ;
			BYTE cbThreeLineCount = 0 ;
			BYTE cbThreeLineCard[20] ;
            
			while (cbLeftCardCount>=cbTurnCardCount && bFindThreeLine)
			{
				BYTE cbLastCard = cbTmpCard[cbFirstCard] ;
				BYTE cbSameCount = 1 ;
				cbThreeLineCount = 0 ;
				bFindThreeLine = false ;
				for(BYTE i=cbFirstCard+1 ; i<cbLeftCardCount+cbFirstCard ; ++i)
				{
					while (GetCardValue(cbLastCard)==GetCardValue(cbTmpCard[i]) && i<cbLeftCardCount+cbFirstCard)
					{
						++cbSameCount;
						++i ;
					}
                    
					BYTE cbLastThreeCardValue ;
					if(cbThreeLineCount>0) cbLastThreeCardValue = GetCardLogicValue(cbThreeLineCard[cbThreeLineCount-1]) ;
                    
					if((cbSameCount<3 || (cbThreeLineCount>0&&(cbLastThreeCardValue-GetCardLogicValue(cbLastCard))!=1)) && i<=cbLeftCardCount+cbFirstCard)
					{
						if(cbThreeLineCount>=cbTurnCardCount) break ;
                        
						if(cbSameCount>=3) i-= 3 ;
						cbLastCard = cbTmpCard[i] ;
						cbThreeLineCount = 0 ;
					}
					else if(cbSameCount>=3)
					{
						cbThreeLineCard[cbThreeLineCount] = cbTmpCard[i-cbSameCount] ;
						cbThreeLineCard[cbThreeLineCount+1] = cbTmpCard[i-cbSameCount+1] ;
						cbThreeLineCard[cbThreeLineCount+2] = cbTmpCard[i-cbSameCount+2] ;
						cbThreeLineCount += 3 ;
                        
						if(i==(cbLeftCardCount+cbFirstCard-3))
							if((GetCardLogicValue(cbLastCard)-GetCardLogicValue(cbTmpCard[i]))==1 && (GetCardLogicValue(cbTmpCard[i])==GetCardLogicValue(cbTmpCard[i+1])) && (GetCardLogicValue(cbTmpCard[i])==GetCardLogicValue(cbTmpCard[i+2])))
							{
								cbThreeLineCard[cbThreeLineCount] = cbTmpCard[i] ;
								cbThreeLineCard[cbThreeLineCount+1] = cbTmpCard[i+1] ;
								cbThreeLineCard[cbThreeLineCount+2] = cbTmpCard[i+2] ;
								cbThreeLineCount += 3 ;
								break ;
							}
                        
					}
                    
					cbLastCard = cbTmpCard[i] ;
					cbSameCount = 1 ;
				}
                
				if(cbThreeLineCount>=cbTurnCardCount)
				{
					BYTE Index ;
					BYTE cbStart=0 ;
					while (GetCardLogicValue(cbThreeLineCard[cbStart])>GetCardLogicValue(cbTurnCardData[0]) && ((cbThreeLineCount-cbStart)>=cbTurnCardCount))
					{
						Index = CardTypeResult[CT_THREE_LINE].cbCardTypeCount ;
						CardTypeResult[CT_THREE_LINE].cbCardType = CT_THREE_LINE ;
						CopyMemory(CardTypeResult[CT_THREE_LINE].cbCardData[Index], cbThreeLineCard+cbStart, sizeof(BYTE)*cbTurnCardCount);
						CardTypeResult[CT_THREE_LINE].cbEachHandCardCount[Index] = cbTurnCardCount;
						CardTypeResult[CT_THREE_LINE].cbCardTypeCount++ ;
						cbStart += 3;
					}
                    
					RemoveCard(cbThreeLineCard, cbThreeLineCount, cbTmpCard, cbFirstCard+cbLeftCardCount) ;
					bFindThreeLine=true ;
					cbLeftCardCount -= cbThreeLineCount ;
				}
			}
            
			break;
		}
        case CT_THREE_LINE_TAKE_ONE:
		{
			BYTE cbTurnThreeCard[MAX_COUNT];
			BYTE cbTurnThreeCount=0;
			BYTE cbHandThreeCard[MAX_COUNT];
			BYTE cbHandThreeCount=0 ;
			BYTE cbSingleCardCount=cbTurnCardCount/4;
            
			BYTE cbAllBomCardData[MAX_COUNT] ;
			BYTE cbAllBomCardCount=0 ;
			GetAllBomCard(cbTmpCard, cbHandCardCount, cbAllBomCardData, cbAllBomCardCount) ;
			RemoveCard(cbAllBomCardData, cbAllBomCardCount, cbTmpCard, cbHandCardCount) ;
            
			GetAllThreeCard(cbTurnCardData, cbTurnCardCount, cbTurnThreeCard, cbTurnThreeCount) ;
            
			BYTE cbFirstCard = 0 ;
            
			if(cbTurnThreeCount>3)
				for(BYTE i=0 ; i<cbHandCardCount-cbAllBomCardCount ; ++i)
					if(GetCardLogicValue(cbTmpCard[i])<15)
					{
						cbFirstCard = i ;
						break ;
					}
            
            GetAllThreeCard(cbTmpCard+cbFirstCard, cbHandCardCount-cbFirstCard-cbAllBomCardCount, cbHandThreeCard, cbHandThreeCount) ;
            
            if(cbHandThreeCount<cbTurnThreeCount || (cbHandThreeCount>0&&GetCardLogicValue(cbHandThreeCard[0])<GetCardLogicValue(cbTurnThreeCard[0]))) return ;
            
            for(BYTE i=0; i<cbHandThreeCount; i+=3)
            {
                BYTE cbLastLogicCard=GetCardLogicValue(cbHandThreeCard[i]);
                BYTE cbThreeLineCard[MAX_COUNT];
                BYTE cbThreeLineCardCount=3;
                cbThreeLineCard[0]=cbHandThreeCard[i];
                cbThreeLineCard[1]=cbHandThreeCard[i+1];
                cbThreeLineCard[2]=cbHandThreeCard[i+2];
                for(BYTE j=i+3; j<cbHandThreeCount; j+=3)
                {
                    if(1!=(cbLastLogicCard-(GetCardLogicValue(cbHandThreeCard[j]))) || cbThreeLineCardCount==cbTurnThreeCount) break;
                    
                    cbLastLogicCard=GetCardLogicValue(cbHandThreeCard[j]);
                    cbThreeLineCard[cbThreeLineCardCount]=cbHandThreeCard[j];
                    cbThreeLineCard[cbThreeLineCardCount+1]=cbHandThreeCard[j+1];
                    cbThreeLineCard[cbThreeLineCardCount+2]=cbHandThreeCard[j+2];
                    cbThreeLineCardCount += 3;
                }
                if(cbThreeLineCardCount==cbTurnThreeCount && GetCardLogicValue(cbThreeLineCard[0])>GetCardLogicValue(cbTurnThreeCard[0]))
                {
                    BYTE Index ;
                    
                    BYTE cbRemainCard[MAX_COUNT];
                    CopyMemory(cbRemainCard, cbTmpCard, (cbHandCardCount-cbAllBomCardCount)*sizeof(BYTE));
                    RemoveCard(cbThreeLineCard, cbTurnThreeCount, cbRemainCard, (cbHandCardCount-cbAllBomCardCount)) ;
                    
                    BYTE cbComCard[5];
                    BYTE cbComResCard[254][5] ;
                    BYTE cbComResLen=0 ;
                    Combination(cbComCard, 0, cbComResCard, cbComResLen, cbRemainCard, cbSingleCardCount, (cbHandCardCount-cbAllBomCardCount)-cbTurnThreeCount, cbSingleCardCount);
                    for(BYTE i=0; i<cbComResLen; ++i)
                    {
                        Index = CardTypeResult[CT_THREE_LINE_TAKE_ONE].cbCardTypeCount ;
                        CardTypeResult[CT_THREE_LINE_TAKE_ONE].cbCardType = CT_THREE_LINE_TAKE_ONE;
                        
                        CopyMemory(CardTypeResult[CT_THREE_LINE_TAKE_ONE].cbCardData[Index], cbThreeLineCard, sizeof(BYTE)*cbTurnThreeCount);
                        CopyMemory(CardTypeResult[CT_THREE_LINE_TAKE_ONE].cbCardData[Index]+cbTurnThreeCount, cbComResCard[i], cbSingleCardCount) ;
                        CardTypeResult[CT_THREE_LINE_TAKE_ONE].cbEachHandCardCount[Index] = cbTurnCardCount ;
                        CardTypeResult[CT_THREE_LINE_TAKE_ONE].cbCardTypeCount++ ;
                    }
                    
                }
            }
            
            break;
		}
        case CT_THREE_LINE_TAKE_TWO:
		{
			BYTE cbTurnThreeCard[MAX_COUNT];
			BYTE cbTurnThreeCount=0;
			BYTE cbHandThreeCard[MAX_COUNT];
			BYTE cbHandThreeCount=0 ;
			BYTE cbDoubleCardCount=cbTurnCardCount/5;
            
			GetAllThreeCard(cbTurnCardData, cbTurnCardCount, cbTurnThreeCard, cbTurnThreeCount) ;
            
			BYTE cbFirstCard = 0 ;
            
			if(cbTurnThreeCount>3)
				for(BYTE i=0 ; i<cbHandCardCount ; ++i)	if(GetCardLogicValue(cbTmpCard[i])<15)	{cbFirstCard = i ; break ;}
            
            GetAllThreeCard(cbTmpCard+cbFirstCard, cbHandCardCount-cbFirstCard, cbHandThreeCard, cbHandThreeCount) ;
            
            if(cbHandThreeCount<cbTurnThreeCount || (cbHandThreeCount>0&&GetCardLogicValue(cbHandThreeCard[0])<GetCardLogicValue(cbTurnThreeCard[0]))) return ;
            
            for(BYTE i=0; i<cbHandThreeCount; i+=3)
            {
                BYTE cbLastLogicCard=GetCardLogicValue(cbHandThreeCard[i]);
                BYTE cbThreeLineCard[MAX_COUNT];
                BYTE cbThreeLineCardCount=3;
                cbThreeLineCard[0]=cbHandThreeCard[i];
                cbThreeLineCard[1]=cbHandThreeCard[i+1];
                cbThreeLineCard[2]=cbHandThreeCard[i+2];
                for(BYTE j=i+3; j<cbHandThreeCount; j+=3)
                {
                    if(1!=(cbLastLogicCard-(GetCardLogicValue(cbHandThreeCard[j]))) || cbThreeLineCardCount==cbTurnThreeCount) break;
                    
                    cbLastLogicCard=GetCardLogicValue(cbHandThreeCard[j]);
                    cbThreeLineCard[cbThreeLineCardCount]=cbHandThreeCard[j];
                    cbThreeLineCard[cbThreeLineCardCount+1]=cbHandThreeCard[j+1];
                    cbThreeLineCard[cbThreeLineCardCount+2]=cbHandThreeCard[j+2];
                    cbThreeLineCardCount += 3;
                }
                if(cbThreeLineCardCount==cbTurnThreeCount && GetCardLogicValue(cbThreeLineCard[0])>GetCardLogicValue(cbTurnThreeCard[0]))
                {
                    BYTE Index ;
                    
                    BYTE cbRemainCard[MAX_COUNT];
                    CopyMemory(cbRemainCard, cbTmpCard, cbHandCardCount*sizeof(BYTE));
                    RemoveCard(cbThreeLineCard, cbTurnThreeCount, cbRemainCard, cbHandCardCount) ;
                    
                    BYTE cbAllDoubleCardData[MAX_COUNT] ;
                    BYTE cbAllDoubleCardCount=0 ;
                    GetAllDoubleCard(cbRemainCard, cbHandCardCount-cbTurnThreeCount, cbAllDoubleCardData, cbAllDoubleCardCount) ;
                    
                    
                    BYTE cbDoubleCardIndex[10];
                    for(BYTE i=0, j=0; i<cbAllDoubleCardCount; i+=2, ++j)
                        cbDoubleCardIndex[j]=i ;
                    
                    BYTE cbComCard[5];
                    BYTE cbComResCard[254][5] ;
                    BYTE cbComResLen=0 ;
                    
                    Combination(cbComCard, 0, cbComResCard, cbComResLen, cbDoubleCardIndex, cbDoubleCardCount, cbAllDoubleCardCount/2, cbDoubleCardCount);
                    for(BYTE i=0; i<cbComResLen; ++i)
                    {
                        Index = CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbCardTypeCount ;
                        CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbCardType = CT_THREE_LINE_TAKE_TWO ;
                        
                        CopyMemory(CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbCardData[Index], cbThreeLineCard, sizeof(BYTE)*cbTurnThreeCount);
                        for(BYTE j=0, k=0; j<cbDoubleCardCount; ++j, k+=2)
                        {
                            CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbCardData[Index][cbTurnThreeCount+k] = cbAllDoubleCardData[cbComResCard[i][j]];
                            CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbCardData[Index][cbTurnThreeCount+k+1] = cbAllDoubleCardData[cbComResCard[i][j]+1];
                        }
                        CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbEachHandCardCount[Index] = cbTurnCardCount ;
                        
                        CardTypeResult[CT_THREE_LINE_TAKE_TWO].cbCardTypeCount++ ;
                    }
                    
                }
            }
            
            break;
		}
        case CT_FOUR_LINE_TAKE_ONE:
		{
			BYTE cbFirstCard = 0 ;
			for(BYTE i=0 ; i<cbHandCardCount ; ++i)	if(GetCardColor(cbTmpCard[i])!=0x40)	{cbFirstCard = i ; break ;}
            
			BYTE cbHandAllFourCardData[MAX_COUNT] ;
			BYTE cbHandAllFourCardCount=0;
			BYTE cbTurnAllFourCardData[MAX_COUNT];
			BYTE cbTurnAllFourCardCount=0;
			GetAllBomCard(cbTmpCard+cbFirstCard, cbHandCardCount-cbFirstCard, cbHandAllFourCardData, cbHandAllFourCardCount) ;
			GetAllBomCard(cbTurnCardData, cbTurnCardCount, cbTurnAllFourCardData, cbTurnAllFourCardCount) ;
            
			if(cbHandAllFourCardCount>0 && GetCardLogicValue(cbHandAllFourCardData[0])<GetCardLogicValue(cbTurnAllFourCardData[0])) return ;
            
            
			BYTE cbCanOutFourCardData[MAX_COUNT] ;
			BYTE cbCanOutFourCardCount=0 ;
			for(BYTE i=0; i<cbHandAllFourCardCount; i+=4)
			{
				if(GetCardLogicValue(cbHandAllFourCardData[i])>GetCardLogicValue(cbTurnAllFourCardData[0]))
				{
					cbCanOutFourCardData[cbCanOutFourCardCount] = cbHandAllFourCardData[i] ;
					cbCanOutFourCardData[cbCanOutFourCardCount+1] = cbHandAllFourCardData[i+1] ;
					cbCanOutFourCardData[cbCanOutFourCardCount+2] = cbHandAllFourCardData[i+2] ;
					cbCanOutFourCardData[cbCanOutFourCardCount+3] = cbHandAllFourCardData[i+3] ;
					cbCanOutFourCardCount += 4 ;
				}
			}
            
			if((cbHandCardCount-cbCanOutFourCardCount) < (cbTurnCardCount-cbTurnAllFourCardCount)) return ;
            
			BYTE cbRemainCard[MAX_COUNT];
			CopyMemory(cbRemainCard, cbTmpCard, cbHandCardCount*sizeof(BYTE));
			RemoveCard(cbCanOutFourCardData, cbCanOutFourCardCount, cbRemainCard, cbHandCardCount) ;
			for(BYTE Start=0; Start<cbCanOutFourCardCount; Start += 4)
			{
				BYTE Index ;
				BYTE cbComCard[5];
				BYTE cbComResCard[254][5] ;
				BYTE cbComResLen=0 ;
				Combination(cbComCard, 0, cbComResCard, cbComResLen, cbRemainCard, 2, cbHandCardCount-cbCanOutFourCardCount, 2);
				for(BYTE i=0; i<cbComResLen; ++i)
				{
					if(GetCardValue(cbComResCard[i][0])==GetCardValue(cbComResCard[i][1])) continue ;
                    
					Index=CardTypeResult[CT_FOUR_LINE_TAKE_ONE].cbCardTypeCount ;
					CardTypeResult[CT_FOUR_LINE_TAKE_ONE].cbCardType = CT_FOUR_LINE_TAKE_ONE ;
					CopyMemory(CardTypeResult[CT_FOUR_LINE_TAKE_ONE].cbCardData[Index], cbCanOutFourCardData+Start, 4) ;
					CardTypeResult[CT_FOUR_LINE_TAKE_ONE].cbCardData[Index][4] = cbComResCard[i][0] ;
					CardTypeResult[CT_FOUR_LINE_TAKE_ONE].cbCardData[Index][4+1] = cbComResCard[i][1] ;
					CardTypeResult[CT_FOUR_LINE_TAKE_ONE].cbEachHandCardCount[Index] = 6 ;
					CardTypeResult[CT_FOUR_LINE_TAKE_ONE].cbCardTypeCount++ ;
				}
			}
            
            
			break;
		}
        case CT_FOUR_LINE_TAKE_TWO:
		{
			BYTE cbFirstCard = 0 ;
			for(BYTE i=0 ; i<cbHandCardCount ; ++i)	if(GetCardColor(cbTmpCard[i])!=0x40)	{cbFirstCard = i ; break ;}
            
			BYTE cbHandAllFourCardData[MAX_COUNT] ;
			BYTE cbHandAllFourCardCount=0;
			BYTE cbTurnAllFourCardData[MAX_COUNT];
			BYTE cbTurnAllFourCardCount=0;
            
			GetAllBomCard(cbTmpCard+cbFirstCard, cbHandCardCount-cbFirstCard, cbHandAllFourCardData, cbHandAllFourCardCount) ;
			GetAllBomCard(cbTurnCardData, cbTurnCardCount, cbTurnAllFourCardData, cbTurnAllFourCardCount) ;
            
			if(cbHandAllFourCardCount>0 && GetCardLogicValue(cbHandAllFourCardData[0])<GetCardLogicValue(cbTurnAllFourCardData[0])) return ;
            
            
			BYTE cbCanOutFourCardData[MAX_COUNT] ;
			BYTE cbCanOutFourCardCount=0 ;
            
			for(BYTE i=0; i<cbHandAllFourCardCount; i+=4)
			{
				if(GetCardLogicValue(cbHandAllFourCardData[i])>GetCardLogicValue(cbTurnAllFourCardData[0]))
				{
					cbCanOutFourCardData[cbCanOutFourCardCount] = cbHandAllFourCardData[i] ;
					cbCanOutFourCardData[cbCanOutFourCardCount+1] = cbHandAllFourCardData[i+1] ;
					cbCanOutFourCardData[cbCanOutFourCardCount+2] = cbHandAllFourCardData[i+2] ;
					cbCanOutFourCardData[cbCanOutFourCardCount+3] = cbHandAllFourCardData[i+3] ;
					cbCanOutFourCardCount += 4 ;
				}
			}
            
			if((cbHandCardCount-cbCanOutFourCardCount) < (cbTurnCardCount-cbTurnAllFourCardCount)) return ;
            
			BYTE cbRemainCard[MAX_COUNT];
			CopyMemory(cbRemainCard, cbTmpCard, cbHandCardCount*sizeof(BYTE));
			RemoveCard(cbCanOutFourCardData, cbCanOutFourCardCount, cbRemainCard, cbHandCardCount) ;
			for(BYTE Start=0; Start<cbCanOutFourCardCount; Start += 4)
			{
				BYTE cbAllDoubleCardData[MAX_COUNT] ;
				BYTE cbAllDoubleCardCount=0 ;
				GetAllDoubleCard(cbRemainCard, cbHandCardCount-cbCanOutFourCardCount, cbAllDoubleCardData, cbAllDoubleCardCount) ;
                
                
				BYTE cbDoubleCardIndex[10];
				for(BYTE i=0, j=0; i<cbAllDoubleCardCount; i+=2, ++j)
					cbDoubleCardIndex[j]=i ;
                
				BYTE cbComCard[5];
				BYTE cbComResCard[254][5] ;
				BYTE cbComResLen=0 ;
                
				Combination(cbComCard, 0, cbComResCard, cbComResLen, cbDoubleCardIndex, 2, cbAllDoubleCardCount/2, 2);
				for(BYTE i=0; i<cbComResLen; ++i)
				{
					BYTE Index = CardTypeResult[CT_FOUR_LINE_TAKE_TWO].cbCardTypeCount ;
					CardTypeResult[CT_FOUR_LINE_TAKE_TWO].cbCardType = CT_FOUR_LINE_TAKE_TWO ;
					CopyMemory(CardTypeResult[CT_FOUR_LINE_TAKE_TWO].cbCardData[Index], cbCanOutFourCardData+Start, 4) ;
                    
					for(BYTE j=0, k=0; j<4; ++j, k+=2)
					{
						CardTypeResult[CT_FOUR_LINE_TAKE_TWO].cbCardData[Index][4+k] = cbAllDoubleCardData[cbComResCard[i][j]];
						CardTypeResult[CT_FOUR_LINE_TAKE_TWO].cbCardData[Index][4+k+1] = cbAllDoubleCardData[cbComResCard[i][j]+1];
					}
                    
					CardTypeResult[CT_FOUR_LINE_TAKE_TWO].cbEachHandCardCount[Index] = 8 ;
					CardTypeResult[CT_FOUR_LINE_TAKE_TWO].cbCardTypeCount++ ;
				}
			}
			break;
		}
        case CT_BOMB_CARD:
		{
			BYTE cbAllBomCardData[MAX_COUNT] ;
			BYTE cbAllBomCardCount=0 ;
			GetAllBomCard(cbTmpCard, cbHandCardCount, cbAllBomCardData, cbAllBomCardCount) ;
			printf("cbAllBomCardCount=%d\n",cbAllBomCardCount);
			BYTE cbFirstBom=0 ;
			BYTE Index=0;
			if(cbAllBomCardCount>0 && cbAllBomCardData[0]==0x4F)
			{
				Index = CardTypeResult[CT_BOMB_CARD].cbCardTypeCount ;
				CardTypeResult[CT_BOMB_CARD].cbCardType = CT_BOMB_CARD ;
				CardTypeResult[CT_BOMB_CARD].cbCardData[Index][0] = 0x4F ;
				CardTypeResult[CT_BOMB_CARD].cbCardData[Index][1] = 0x4E ;
				CardTypeResult[CT_BOMB_CARD].cbEachHandCardCount[Index] = 2 ;
				CardTypeResult[CT_BOMB_CARD].cbCardTypeCount++ ;
				cbFirstBom=2;
			}
			for(BYTE i=cbFirstBom; i<cbAllBomCardCount; i+=4)
			{
				if(GetCardLogicValue(cbAllBomCardData[i])>GetCardLogicValue(cbTurnCardData[0]))
				{
					Index = CardTypeResult[CT_BOMB_CARD].cbCardTypeCount ;
					CardTypeResult[CT_BOMB_CARD].cbCardType = CT_BOMB_CARD ;
					CopyMemory(CardTypeResult[CT_BOMB_CARD].cbCardData[Index], cbAllBomCardData+i, 4) ;
					CardTypeResult[CT_BOMB_CARD].cbEachHandCardCount[Index] = 4 ;
					CardTypeResult[CT_BOMB_CARD].cbCardTypeCount++ ;
				}
			}
			break;
		}
        case CT_MISSILE_CARD:
		{
			break;
		}
        default:
            break;
	}
    
}

void DDZCGameLogicSingle::Combination(BYTE cbCombineCardData[], BYTE cbResComLen,  BYTE cbResultCardData[100][5], BYTE &cbResCardLen,BYTE cbSrcCardData[] , BYTE cbCombineLen1, BYTE cbSrcLen, const BYTE cbCombineLen2)
{
    
	if( cbResComLen == cbCombineLen2 )
	{
		CopyMemory(&cbResultCardData[cbResCardLen], cbCombineCardData, cbResComLen) ;
		++cbResCardLen ;
        
	}
	else
	{
		if(cbCombineLen1 >= 1 && cbSrcLen > 0 && (cbSrcLen+1) >= 0 ){
			cbCombineCardData[cbCombineLen2-cbCombineLen1] =  cbSrcCardData[0];
			++cbResComLen ;
			Combination(cbCombineCardData,cbResComLen, cbResultCardData, cbResCardLen, cbSrcCardData+1,cbCombineLen1-1, cbSrcLen-1, cbCombineLen2);
            
			--cbResComLen;
			Combination(cbCombineCardData,cbResComLen, cbResultCardData, cbResCardLen, cbSrcCardData+1,cbCombineLen1, cbSrcLen-1, cbCombineLen2);
		}
	}
}

void DDZCGameLogicSingle::Permutation(BYTE *list, int m, int n, BYTE result[][4], BYTE &len)
{
	int j,temp;
	if(m == n){
		for(j = 0; j < n; j++)
			result[len][j]=list[j];
		len++ ;
	}
	else{
		for(j = m; j < n; j++){
			temp = list[m] ;
			list[m] = list[j];
			list[j] = temp ;
			Permutation(list,m+1,n,result,len);
			temp = list[m] ;
			list[m] = list[j];
			list[j] = temp ;
		}
	}
}

BYTE DDZCGameLogicSingle::AnalyseSinleCardCount(BYTE const cbHandCardData[], BYTE const cbHandCardCount, BYTE const cbWantOutCardData[], BYTE const cbWantOutCardCount, BYTE cbSingleCardData[])
{
	if(cbHandCardCount<=0) return MAX_COUNT + 5 ;
    
	BYTE cbRemainCard[MAX_COUNT] ;
	BYTE cbRemainCardCount=0 ;
	CopyMemory(cbRemainCard, cbHandCardData, cbHandCardCount) ;
	SortCardList(cbRemainCard, cbHandCardCount, ST_ORDER) ;
    
	if(cbWantOutCardCount!=0) RemoveCard(cbWantOutCardData, cbWantOutCardCount, cbRemainCard, cbHandCardCount) ;
	cbRemainCardCount = cbHandCardCount-cbWantOutCardCount ;
    
	typedef void (DDZCGameLogicSingle::*pGetAllCardFun)(BYTE const [], BYTE const , BYTE[], BYTE &);
    
	pGetAllCardFun GetAllCardFunArray[4] ;
	GetAllCardFunArray[0] = &DDZCGameLogicSingle::GetAllBomCard ;
	GetAllCardFunArray[1] = &DDZCGameLogicSingle::GetAllLineCard ;
	GetAllCardFunArray[2] = &DDZCGameLogicSingle::GetAllThreeCard ;
	GetAllCardFunArray[3] = &DDZCGameLogicSingle::GetAllDoubleCard ;
    
	BYTE cbIndexArray[4] = {0,1,2,3} ;
	BYTE cbPermutationRes[24][4] ;
	BYTE cbLen=0 ;
	Permutation(cbIndexArray, 0, 4, cbPermutationRes, cbLen) ;
	if(cbLen!=24) return MAX_COUNT + 5 ;
    
	BYTE cbMinSingleCardCount = MAX_COUNT + 5 ;
    
	for(BYTE i=0; i<24; ++i)
	{
		BYTE cbTmpCardData[MAX_COUNT] ;
		BYTE cbTmpCardCount = cbRemainCardCount ;
		CopyMemory(cbTmpCardData, cbRemainCard, cbRemainCardCount) ;
        
		for(BYTE j=0; j<4; ++j)
		{
			BYTE Index = cbPermutationRes[i][j] ;
            
			if(Index<0 || Index>=4) return MAX_COUNT + 5 ;
            
			pGetAllCardFun pTmpGetAllCardFun = GetAllCardFunArray[Index] ;
            
			BYTE cbGetCardData[MAX_COUNT] ;
			BYTE cbGetCardCount=0 ;
			
			((*this).*pTmpGetAllCardFun)(cbTmpCardData, cbTmpCardCount, cbGetCardData, cbGetCardCount) ;
            
			if(cbGetCardCount!=0) RemoveCard(cbGetCardData, cbGetCardCount, cbTmpCardData, cbTmpCardCount) ;
			cbTmpCardCount -= cbGetCardCount ;
		}
        
		BYTE cbSingleCard[MAX_COUNT] ;
		BYTE cbSingleCardCount=0 ;
		GetAllSingleCard(cbTmpCardData, cbTmpCardCount, cbSingleCard, cbSingleCardCount) ;
		if(cbMinSingleCardCount> cbSingleCardCount)
		{
			cbMinSingleCardCount = cbSingleCardCount ;
            
			if(cbSingleCardData!=NULL)
			{
				CopyMemory(cbSingleCardData, cbSingleCard, cbSingleCardCount) ;
			}
		}
	}
    
	if (cbWantOutCardCount > 0)
	{
		BYTE cbCardType = GetCardType(cbWantOutCardData, cbWantOutCardCount) ;
		if (cbCardType == CT_THREE_LINE_TAKE_ONE || cbCardType == CT_THREE_LINE_TAKE_TWO)
            
			for (BYTE i = 3; i < cbWantOutCardCount; ++i)
			{
				if (GetCardLogicValue(cbWantOutCardData[i]) >= 14) cbMinSingleCardCount += 3 ;
			}
	}
    
	if ( GetCardType(cbWantOutCardData, cbWantOutCardCount) == CT_DOUBLE )
	{
		BYTE cbAllThreeCardData[MAX_COUNT], cbAllThreeCount ;
		BYTE cbAllLineCardData[MAX_COUNT], cbAllLineCount ;
        
		GetAllThreeCard(cbHandCardData, cbHandCardCount, cbAllThreeCardData, cbAllThreeCount) ;
		GetAllLineCard( cbHandCardData, cbHandCardCount, cbAllLineCardData, cbAllLineCount ) ;
        
		BYTE cbThreeCardValue = 0 ;
		for ( BYTE i = 0; i < cbAllThreeCount; ++i)
			for ( BYTE j = 0; j < cbWantOutCardCount; ++j)
				if ( GetCardLogicValue(cbWantOutCardData[j]) == GetCardLogicValue(cbAllThreeCardData[i]) )
				{
					cbThreeCardValue = GetCardValue( cbWantOutCardData[j] ) ;
					break ;
				}
        
        bool bInLineCard = false ;
        for ( BYTE cbLineCardIndex = 0; cbLineCardIndex < cbAllLineCount; ++cbLineCardIndex )
            if ( GetCardValue( cbAllLineCardData[cbLineCardIndex] ) == cbThreeCardValue )
            {
                bInLineCard = true ;
                break ;
            }
        if ( !bInLineCard && cbThreeCardValue != 0 ) cbMinSingleCardCount += 2 ;
	}
    
	if(cbWantOutCardCount!=0)
	{
		BYTE cbBombCard[20] ;
		BYTE cbBombCardCount=0;
		GetAllBomCard(cbHandCardData, cbHandCardCount, cbBombCard, cbBombCardCount) ;
        
		BYTE cbCardType = GetCardType(cbWantOutCardData, cbWantOutCardCount) ;
        
		if(cbBombCardCount>0 && cbCardType<CT_BOMB_CARD)
		{
			for(BYTE i = GetCardColor(cbBombCard[0]) == 4 ? 2 : 0; i<cbBombCardCount; i += 4)
				for(BYTE j=0; j<cbWantOutCardCount; ++j)
				{
					if(GetCardValue( cbBombCard[i] ) == GetCardValue( cbWantOutCardData[j] ) && GetCardLogicValue(cbWantOutCardData[j])<15 &&
                       cbCardType!=CT_SINGLE_LINE && cbCardType!=CT_DOUBLE_LINE)
						return MAX_COUNT + 5 ;
                    
					else if ( GetCardValue( cbBombCard[i] ) == GetCardValue( cbWantOutCardData[j] ) && GetCardLogicValue(cbWantOutCardData[j])<15 &&
                             ( cbCardType == CT_SINGLE_LINE || cbCardType == CT_DOUBLE_LINE) )
						cbMinSingleCardCount += 2 ;
				}
            
            if (cbCardType == CT_SINGLE_LINE)
            {
                BYTE cbBombCount = 0 ;
                
                for (BYTE i = GetCardColor(cbBombCard[0]) == 4 ? 2 : 0; i < cbBombCardCount; i += 4)
                    for (BYTE j=0; j < cbWantOutCardCount; ++j)
                        if ( GetCardValue( cbBombCard[i] ) == GetCardValue( cbWantOutCardData[j] ) ) ++cbBombCount ;
                
                if (cbBombCount >= 2) return  MAX_COUNT ;
                
                tagAnalyseResultA AnalyseResult;
                AnalysebCardDataA(cbHandCardData, cbHandCardCount,AnalyseResult) ;
                
                BYTE bThreeCount = 0 ;
                
                for (BYTE i = 0; i < AnalyseResult.bThreeCount; ++i)
                    for (BYTE j = 0; j < cbWantOutCardCount; ++j)
                        if (GetCardValue(cbWantOutCardData[j]) == GetCardValue(AnalyseResult.m_bTCardData[3 * i])) ++bThreeCount ;
                
                if (bThreeCount + cbBombCount >= 2) return  MAX_COUNT + 5 ;
                
            }
		}
	}
    
	return cbMinSingleCardCount ;
}

